From efbbdc90c547939a20d8eefae9bfbdabaeac56b1 Mon Sep 17 00:00:00 2001 From: Luca Ghersi Date: Fri, 4 Aug 2017 11:22:34 +0200 Subject: [PATCH] base change --- .../Ofscrm.PluginRegistration.Tests.csproj | 116 + .../Properties/AssemblyInfo.cs | 20 + Ofscrm.PluginRegistration.Tests/UnitTest1.cs | 22 + Ofscrm.PluginRegistration.Tests/app.config | 14 + .../packages.config | 11 + Ofscrm.PluginRegistration/CommandBase.cs | 56 + .../Entities/PluginAssembly.cs | 498 +++++ .../Entities/PluginType.cs | 449 ++++ .../Entities/SdkMessage.cs | 348 +++ .../Entities/SdkMessageFilter.cs | 300 +++ .../Entities/SdkMessageProcessingStep.cs | 660 ++++++ .../Entities/SdkMessageProcessingStepImage.cs | 420 ++++ .../SdkMessageProcessingStepSecureConfig.cs | 216 ++ .../Entities/SdkMessageProcessingStepState.cs | 17 + .../Entities/ServiceEndpoint.cs | 377 ++++ .../Entities/SystemUser.cs | 1878 +++++++++++++++++ .../Entities/Transformation/Magic.cs | 25 + .../Helpers/AppDomainContext.cs | 104 + .../Helpers/AssemblyReader.cs | 192 ++ .../Helpers/AssemblyResolver.cs | 148 ++ .../Helpers/CrmServiceEndpoint.cs | 369 ++++ .../Helpers/OrganizationConnectionOptions.cs | 12 + .../Helpers/OrganizationHelper.cs | 1210 +++++++++++ .../Helpers/OrganizationServiceExtensions.cs | 59 + .../Helpers/RegistrationHelper.cs | 1022 +++++++++ .../Ofscrm.PluginRegistration.csproj | 134 ++ .../Properties/AssemblyInfo.cs | 36 + .../UpdatePluginsCommand.cs | 634 ++++++ .../UpdatePluginsCommandOptions.cs | 7 + .../Wrappers/CrmAttribute.cs | 129 ++ .../Wrappers/CrmEntityDictionary.cs | 102 + .../Wrappers/CrmMessage.cs | 569 +++++ .../Wrappers/CrmMessageEntity.cs | 264 +++ .../Wrappers/CrmOrganization.cs | 1247 +++++++++++ .../Wrappers/CrmPlugin.cs | 746 +++++++ .../Wrappers/CrmPluginAssembly.cs | 602 ++++++ .../Wrappers/CrmPluginImage.cs | 706 +++++++ .../Wrappers/CrmPluginStep.cs | 1033 +++++++++ Ofscrm.PluginRegistration/Wrappers/CrmUser.cs | 92 + Ofscrm.PluginRegistration/app.config | 14 + Ofscrm.PluginRegistration/packages.config | 12 + PluginRegistration.sln | 16 +- 42 files changed, 14884 insertions(+), 2 deletions(-) create mode 100644 Ofscrm.PluginRegistration.Tests/Ofscrm.PluginRegistration.Tests.csproj create mode 100644 Ofscrm.PluginRegistration.Tests/Properties/AssemblyInfo.cs create mode 100644 Ofscrm.PluginRegistration.Tests/UnitTest1.cs create mode 100644 Ofscrm.PluginRegistration.Tests/app.config create mode 100644 Ofscrm.PluginRegistration.Tests/packages.config create mode 100644 Ofscrm.PluginRegistration/CommandBase.cs create mode 100644 Ofscrm.PluginRegistration/Entities/PluginAssembly.cs create mode 100644 Ofscrm.PluginRegistration/Entities/PluginType.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SdkMessage.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SdkMessageFilter.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStep.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepImage.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepSecureConfig.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepState.cs create mode 100644 Ofscrm.PluginRegistration/Entities/ServiceEndpoint.cs create mode 100644 Ofscrm.PluginRegistration/Entities/SystemUser.cs create mode 100644 Ofscrm.PluginRegistration/Entities/Transformation/Magic.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/AppDomainContext.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/AssemblyReader.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/AssemblyResolver.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/CrmServiceEndpoint.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/OrganizationConnectionOptions.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/OrganizationHelper.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/OrganizationServiceExtensions.cs create mode 100644 Ofscrm.PluginRegistration/Helpers/RegistrationHelper.cs create mode 100644 Ofscrm.PluginRegistration/Ofscrm.PluginRegistration.csproj create mode 100644 Ofscrm.PluginRegistration/Properties/AssemblyInfo.cs create mode 100644 Ofscrm.PluginRegistration/UpdatePluginsCommand.cs create mode 100644 Ofscrm.PluginRegistration/UpdatePluginsCommandOptions.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmAttribute.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmEntityDictionary.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmMessage.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmMessageEntity.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmOrganization.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmPlugin.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmPluginAssembly.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmPluginImage.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmPluginStep.cs create mode 100644 Ofscrm.PluginRegistration/Wrappers/CrmUser.cs create mode 100644 Ofscrm.PluginRegistration/app.config create mode 100644 Ofscrm.PluginRegistration/packages.config diff --git a/Ofscrm.PluginRegistration.Tests/Ofscrm.PluginRegistration.Tests.csproj b/Ofscrm.PluginRegistration.Tests/Ofscrm.PluginRegistration.Tests.csproj new file mode 100644 index 0000000..d2cb1fc --- /dev/null +++ b/Ofscrm.PluginRegistration.Tests/Ofscrm.PluginRegistration.Tests.csproj @@ -0,0 +1,116 @@ + + + + + Debug + AnyCPU + {80420FE9-F185-4DF2-A3BF-9DEBB341849B} + Library + Properties + Ofscrm.PluginRegistration.Tests + Ofscrm.PluginRegistration.Tests + v4.5.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0\lib\net45\Microsoft.Crm.Sdk.Proxy.dll + + + ..\packages\Microsoft.IdentityModel.6.1.7600.16394\lib\net35\Microsoft.IdentityModel.dll + True + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.22.302111727\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.22.302111727\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll + + + ..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0\lib\net45\Microsoft.Xrm.Sdk.dll + + + ..\packages\Microsoft.CrmSdk.Deployment.8.2.0\lib\net45\Microsoft.Xrm.Sdk.Deployment.dll + + + ..\packages\Microsoft.CrmSdk.Workflow.8.2.0\lib\net45\Microsoft.Xrm.Sdk.Workflow.dll + + + ..\packages\Microsoft.CrmSdk.XrmTooling.CoreAssembly.8.2.0.5\lib\net452\Microsoft.Xrm.Tooling.Connector.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {48fc78f2-e0da-4b04-b043-c69e9130a6a4} + Ofscrm.PluginRegistration + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/Ofscrm.PluginRegistration.Tests/Properties/AssemblyInfo.cs b/Ofscrm.PluginRegistration.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4539893 --- /dev/null +++ b/Ofscrm.PluginRegistration.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Ofscrm.PluginRegistration.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Ofscrm.PluginRegistration.Tests")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("80420fe9-f185-4df2-a3bf-9debb341849b")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Ofscrm.PluginRegistration.Tests/UnitTest1.cs b/Ofscrm.PluginRegistration.Tests/UnitTest1.cs new file mode 100644 index 0000000..3e490ba --- /dev/null +++ b/Ofscrm.PluginRegistration.Tests/UnitTest1.cs @@ -0,0 +1,22 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Ofscrm.PluginRegistration.Tests +{ + [TestClass] + public class UpdatePluginsCommandTests + { + [TestMethod] + public void TestMethod1() + { + UpdatePluginsCommandOptions options = new UpdatePluginsCommandOptions + { + PluginsFolder = "C:\\Users\\lghersi\\Projects\\ClientEngage\\Sources\\Product\\Development\\Build\\plugins" + }; + UpdatePluginsCommand command = new UpdatePluginsCommand(options); + + command.ExecuteCommand(); + + Assert.Inconclusive(); + } + } +} diff --git a/Ofscrm.PluginRegistration.Tests/app.config b/Ofscrm.PluginRegistration.Tests/app.config new file mode 100644 index 0000000..874841b --- /dev/null +++ b/Ofscrm.PluginRegistration.Tests/app.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ofscrm.PluginRegistration.Tests/packages.config b/Ofscrm.PluginRegistration.Tests/packages.config new file mode 100644 index 0000000..0a757de --- /dev/null +++ b/Ofscrm.PluginRegistration.Tests/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/CommandBase.cs b/Ofscrm.PluginRegistration/CommandBase.cs new file mode 100644 index 0000000..9a36a53 --- /dev/null +++ b/Ofscrm.PluginRegistration/CommandBase.cs @@ -0,0 +1,56 @@ +using System; +using McTools.Xrm.Connection; +using Microsoft.Xrm.Tooling.Connector; +using Ofscrm.PluginRegistration.Helpers; +using Ofscrm.PluginRegistration.Wrappers; + +namespace Ofscrm.PluginRegistration +{ + public abstract class CommandBase + { + protected CrmOrganization Organization { get; } + + protected CommandBase() + { + Organization = GetOrganization(); + } + + private static ConnectionDetail CreateConnection() + { + ConnectionDetail connection = new ConnectionDetail + { + UseConnectionString = true, + ConnectionString = "AuthType=AD;Url=http://bemeche1crm01.ofscorp.objectway.com/OFSCRMWealthLGHE;", + ConnectionName = "LGHE" + }; + + CrmServiceClient crmServiceClient = connection.GetCrmServiceClient(true); + if (crmServiceClient.IsReady) + { + return connection; + } + + throw new CrmInvalidConnectionException("Connection is not ready."); + } + + private static CrmOrganization GetOrganization() + { + OrganizationConnectionOptions connectionOptions = + new OrganizationConnectionOptions + { + LoadPlugins = true, + LoadAssemblies = true + }; + + return new CrmOrganization(CreateConnection(), connectionOptions); + } + } + + internal class CrmInvalidConnectionException : Exception + { + public CrmInvalidConnectionException(string message):base(message) + { + + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/PluginAssembly.cs b/Ofscrm.PluginRegistration/Entities/PluginAssembly.cs new file mode 100644 index 0000000..1ef9649 --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/PluginAssembly.cs @@ -0,0 +1,498 @@ +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Assembly that contains one or more plug-in types. + /// + [DataContract()] + [EntityLogicalName("pluginassembly")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class PluginAssembly : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + /// + /// Default Constructor. + /// + public PluginAssembly() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "pluginassembly"; + + public const int EntityTypeCode = 4605; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("componentstate")] + public OptionSetValue ComponentState + { + get + { + return GetAttributeValue("componentstate"); + } + } + + /// + /// Bytes of the assembly, in Base64 format. + /// + [AttributeLogicalName("content")] + public string Content + { + get + { + return GetAttributeValue("content"); + } + set + { + OnPropertyChanging("Content"); + SetAttributeValue("content", value); + OnPropertyChanged("Content"); + } + } + + /// + /// Unique identifier of the user who created the plug-in assembly. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the plug-in assembly was created. + /// + [AttributeLogicalName("createdon")] + public System.DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the pluginassembly. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Culture code for the plug-in assembly. + /// + [AttributeLogicalName("culture")] + public string Culture + { + get + { + return GetAttributeValue("culture"); + } + set + { + OnPropertyChanging("Culture"); + SetAttributeValue("culture", value); + OnPropertyChanged("Culture"); + } + } + + /// + /// Customization Level. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Description of the plug-in assembly. + /// + [AttributeLogicalName("description")] + public string Description + { + get + { + return GetAttributeValue("description"); + } + set + { + OnPropertyChanging("Description"); + SetAttributeValue("description", value); + OnPropertyChanged("Description"); + } + } + + /// + /// Information that specifies whether this component should be hidden. + /// + [AttributeLogicalName("ishidden")] + public BooleanManagedProperty IsHidden + { + get + { + return GetAttributeValue("ishidden"); + } + set + { + OnPropertyChanging("IsHidden"); + SetAttributeValue("ishidden", value); + OnPropertyChanged("IsHidden"); + } + } + + /// + /// Information that specifies whether this component is managed. + /// + [AttributeLogicalName("ismanaged")] + public bool? IsManaged + { + get + { + return GetAttributeValue("ismanaged"); + } + } + + /// + /// Information about how the plugin assembly is to be isolated at execution time; None / Sandboxed. + /// + [AttributeLogicalName("isolationmode")] + public OptionSetValue IsolationMode + { + get + { + return GetAttributeValue("isolationmode"); + } + set + { + OnPropertyChanging("IsolationMode"); + SetAttributeValue("isolationmode", value); + OnPropertyChanged("IsolationMode"); + } + } + + /// + /// Major of the assembly version. + /// + [AttributeLogicalName("major")] + public int? Major + { + get + { + return GetAttributeValue("major"); + } + } + + /// + /// Minor of the assembly version. + /// + [AttributeLogicalName("minor")] + public int? Minor + { + get + { + return GetAttributeValue("minor"); + } + } + + /// + /// Unique identifier of the user who last modified the plug-in assembly. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the plug-in assembly was last modified. + /// + [AttributeLogicalName("modifiedon")] + public System.DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the pluginassembly. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Name of the plug-in assembly. + /// + [AttributeLogicalName("name")] + public string Name + { + get + { + return GetAttributeValue("name"); + } + set + { + OnPropertyChanging("Name"); + SetAttributeValue("name", value); + OnPropertyChanged("Name"); + } + } + + /// + /// Unique identifier of the organization with which the plug-in assembly is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("overwritetime")] + public System.DateTime? OverwriteTime + { + get + { + return GetAttributeValue("overwritetime"); + } + } + + /// + /// File name of the plug-in assembly. Used when the source type is set to 1. + /// + [AttributeLogicalName("path")] + public string Path + { + get + { + return GetAttributeValue("path"); + } + set + { + OnPropertyChanging("Path"); + SetAttributeValue("path", value); + OnPropertyChanged("Path"); + } + } + + /// + /// Unique identifier of the plug-in assembly. + /// + [AttributeLogicalName("pluginassemblyid")] + public Guid? PluginAssemblyId + { + get + { + return GetAttributeValue("pluginassemblyid"); + } + set + { + OnPropertyChanging("PluginAssemblyId"); + SetAttributeValue("pluginassemblyid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = System.Guid.Empty; + } + OnPropertyChanged("PluginAssemblyId"); + } + } + + [AttributeLogicalName("pluginassemblyid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + PluginAssemblyId = value; + } + } + + /// + /// Unique identifier of the plug-in assembly. + /// + [AttributeLogicalName("pluginassemblyidunique")] + public Guid? PluginAssemblyIdUnique + { + get + { + return GetAttributeValue("pluginassemblyidunique"); + } + } + + /// + /// Public key token of the assembly. This value can be obtained from the assembly by using reflection. + /// + [AttributeLogicalName("publickeytoken")] + public string PublicKeyToken + { + get + { + return GetAttributeValue("publickeytoken"); + } + set + { + OnPropertyChanging("PublicKeyToken"); + SetAttributeValue("publickeytoken", value); + OnPropertyChanged("PublicKeyToken"); + } + } + + /// + /// Unique identifier of the associated solution. + /// + [AttributeLogicalName("solutionid")] + public Guid? SolutionId + { + get + { + return GetAttributeValue("solutionid"); + } + } + + /// + /// Hash of the source of the assembly. + /// + [AttributeLogicalName("sourcehash")] + public string SourceHash + { + get + { + return GetAttributeValue("sourcehash"); + } + set + { + OnPropertyChanging("SourceHash"); + SetAttributeValue("sourcehash", value); + OnPropertyChanged("SourceHash"); + } + } + + /// + /// Location of the assembly, for example 0=database, 1=on-disk. + /// + [AttributeLogicalName("sourcetype")] + public OptionSetValue SourceType + { + get + { + return GetAttributeValue("sourcetype"); + } + set + { + OnPropertyChanging("SourceType"); + SetAttributeValue("sourcetype", value); + OnPropertyChanged("SourceType"); + } + } + + /// + /// Version number of the assembly. The value can be obtained from the assembly through reflection. + /// + [AttributeLogicalName("version")] + public string Version + { + get + { + return GetAttributeValue("version"); + } + set + { + OnPropertyChanging("Version"); + SetAttributeValue("version", value); + OnPropertyChanged("Version"); + } + } + + /// + /// + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + + /// + /// 1:N pluginassembly_plugintype + /// + [RelationshipSchemaName("pluginassembly_plugintype")] + public IEnumerable pluginassembly_plugintype + { + get + { + return GetRelatedEntities("pluginassembly_plugintype", null); + } + set + { + OnPropertyChanging("pluginassembly_plugintype"); + SetRelatedEntities("pluginassembly_plugintype", null, value); + OnPropertyChanged("pluginassembly_plugintype"); + } + } + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Entities/PluginType.cs b/Ofscrm.PluginRegistration/Entities/PluginType.cs new file mode 100644 index 0000000..435128d --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/PluginType.cs @@ -0,0 +1,449 @@ +using System; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Type that inherits from the IPlugin interface and is contained within a plug-in assembly. + /// + [DataContract()] + [EntityLogicalName("plugintype")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class PluginType : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + /// + /// Default Constructor. + /// + public PluginType() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "plugintype"; + + public const int EntityTypeCode = 4602; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Full path name of the plug-in assembly. + /// + [AttributeLogicalName("assemblyname")] + public string AssemblyName + { + get + { + return GetAttributeValue("assemblyname"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("componentstate")] + public OptionSetValue ComponentState + { + get + { + return GetAttributeValue("componentstate"); + } + } + + /// + /// Unique identifier of the user who created the plug-in type. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the plug-in type was created. + /// + [AttributeLogicalName("createdon")] + public DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the plugintype. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Culture code for the plug-in assembly. + /// + [AttributeLogicalName("culture")] + public string Culture + { + get + { + return GetAttributeValue("culture"); + } + } + + /// + /// Customization level of the plug-in type. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Description of the plug-in type. + /// + [AttributeLogicalName("description")] + public string Description + { + get + { + return GetAttributeValue("description"); + } + set + { + OnPropertyChanging("Description"); + SetAttributeValue("description", value); + OnPropertyChanged("Description"); + } + } + + /// + /// User friendly name for the plug-in. + /// + [AttributeLogicalName("friendlyname")] + public string FriendlyName + { + get + { + return GetAttributeValue("friendlyname"); + } + set + { + OnPropertyChanging("FriendlyName"); + SetAttributeValue("friendlyname", value); + OnPropertyChanged("FriendlyName"); + } + } + + /// + /// + /// + [AttributeLogicalName("ismanaged")] + public bool? IsManaged + { + get + { + return GetAttributeValue("ismanaged"); + } + } + + /// + /// Indicates if the plug-in is a custom activity for workflows. + /// + [AttributeLogicalName("isworkflowactivity")] + public bool? IsWorkflowActivity + { + get + { + return GetAttributeValue("isworkflowactivity"); + } + } + + /// + /// Major of the version number of the assembly for the plug-in type. + /// + [AttributeLogicalName("major")] + public int? Major + { + get + { + return GetAttributeValue("major"); + } + } + + /// + /// Minor of the version number of the assembly for the plug-in type. + /// + [AttributeLogicalName("minor")] + public int? Minor + { + get + { + return GetAttributeValue("minor"); + } + } + + /// + /// Unique identifier of the user who last modified the plug-in type. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the plug-in type was last modified. + /// + [AttributeLogicalName("modifiedon")] + public DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the plugintype. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Name of the plug-in type. + /// + [AttributeLogicalName("name")] + public string Name + { + get + { + return GetAttributeValue("name"); + } + set + { + OnPropertyChanging("Name"); + SetAttributeValue("name", value); + OnPropertyChanged("Name"); + } + } + + /// + /// Unique identifier of the organization with which the plug-in type is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("overwritetime")] + public DateTime? OverwriteTime + { + get + { + return GetAttributeValue("overwritetime"); + } + } + + /// + /// Unique identifier of the plug-in assembly that contains this plug-in type. + /// + [AttributeLogicalName("pluginassemblyid")] + public EntityReference PluginAssemblyId + { + get + { + return GetAttributeValue("pluginassemblyid"); + } + set + { + OnPropertyChanging("PluginAssemblyId"); + SetAttributeValue("pluginassemblyid", value); + OnPropertyChanged("PluginAssemblyId"); + } + } + + /// + /// Unique identifier of the plug-in type. + /// + [AttributeLogicalName("plugintypeid")] + public Guid? PluginTypeId + { + get + { + return GetAttributeValue("plugintypeid"); + } + set + { + OnPropertyChanging("PluginTypeId"); + SetAttributeValue("plugintypeid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("PluginTypeId"); + } + } + + [AttributeLogicalName("plugintypeid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + PluginTypeId = value; + } + } + + /// + /// Unique identifier of the plug-in type. + /// + [AttributeLogicalName("plugintypeidunique")] + public Guid? PluginTypeIdUnique + { + get + { + return GetAttributeValue("plugintypeidunique"); + } + } + + /// + /// Public key token of the assembly for the plug-in type. + /// + [AttributeLogicalName("publickeytoken")] + public string PublicKeyToken + { + get + { + return GetAttributeValue("publickeytoken"); + } + } + + /// + /// Unique identifier of the associated solution. + /// + [AttributeLogicalName("solutionid")] + public Guid? SolutionId + { + get + { + return GetAttributeValue("solutionid"); + } + } + + /// + /// Fully qualified type name of the plug-in type. + /// + [AttributeLogicalName("typename")] + public string TypeName + { + get + { + return GetAttributeValue("typename"); + } + set + { + OnPropertyChanging("TypeName"); + SetAttributeValue("typename", value); + OnPropertyChanged("TypeName"); + } + } + + /// + /// Version number of the assembly for the plug-in type. + /// + [AttributeLogicalName("version")] + public string Version + { + get + { + return GetAttributeValue("version"); + } + } + + /// + /// + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + + /// + /// Group name of workflow custom activity. + /// + [AttributeLogicalName("workflowactivitygroupname")] + public string WorkflowActivityGroupName + { + get + { + return GetAttributeValue("workflowactivitygroupname"); + } + set + { + OnPropertyChanging("WorkflowActivityGroupName"); + SetAttributeValue("workflowactivitygroupname", value); + OnPropertyChanged("WorkflowActivityGroupName"); + } + } + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Entities/SdkMessage.cs b/Ofscrm.PluginRegistration/Entities/SdkMessage.cs new file mode 100644 index 0000000..012d34d --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SdkMessage.cs @@ -0,0 +1,348 @@ +using System; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Message that is supported by the SDK. + /// + [DataContract()] + [EntityLogicalName("sdkmessage")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class SdkMessage : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public SdkMessage() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "sdkmessage"; + + public const int EntityTypeCode = 4606; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Information about whether the SDK message is automatically transacted. + /// + [AttributeLogicalName("autotransact")] + public bool? AutoTransact + { + get + { + return GetAttributeValue("autotransact"); + } + set + { + OnPropertyChanging("AutoTransact"); + SetAttributeValue("autotransact", value); + OnPropertyChanged("AutoTransact"); + } + } + + /// + /// Identifies where a method will be exposed. 0 - Server, 1 - Client, 2 - both. + /// + [AttributeLogicalName("availability")] + public int? Availability + { + get + { + return GetAttributeValue("availability"); + } + set + { + OnPropertyChanging("Availability"); + SetAttributeValue("availability", value); + OnPropertyChanged("Availability"); + } + } + + /// + /// If this is a categorized method, this is the name, otherwise None. + /// + [AttributeLogicalName("categoryname")] + public string CategoryName + { + get + { + return GetAttributeValue("categoryname"); + } + set + { + OnPropertyChanging("CategoryName"); + SetAttributeValue("categoryname", value); + OnPropertyChanged("CategoryName"); + } + } + + /// + /// Unique identifier of the user who created the SDK message. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the SDK message was created. + /// + [AttributeLogicalName("createdon")] + public DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the sdkmessage. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Customization level of the SDK message. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Indicates whether the SDK message should have its requests expanded per primary entity defined in its filters. + /// + [AttributeLogicalName("expand")] + public bool? Expand + { + get + { + return GetAttributeValue("expand"); + } + set + { + OnPropertyChanging("Expand"); + SetAttributeValue("expand", value); + OnPropertyChanged("Expand"); + } + } + + /// + /// Indicates whether the SDK message is private. + /// + [AttributeLogicalName("isprivate")] + public bool? IsPrivate + { + get + { + return GetAttributeValue("isprivate"); + } + set + { + OnPropertyChanging("IsPrivate"); + SetAttributeValue("isprivate", value); + OnPropertyChanged("IsPrivate"); + } + } + + /// + /// Unique identifier of the user who last modified the SDK message. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the SDK message was last modified. + /// + [AttributeLogicalName("modifiedon")] + public DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the sdkmessage. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Name of the SDK message. + /// + [AttributeLogicalName("name")] + public string Name + { + get + { + return GetAttributeValue("name"); + } + set + { + OnPropertyChanging("Name"); + SetAttributeValue("name", value); + OnPropertyChanged("Name"); + } + } + + /// + /// Unique identifier of the organization with which the SDK message is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// Unique identifier of the SDK message entity. + /// + [AttributeLogicalName("sdkmessageid")] + public Guid? SdkMessageId + { + get + { + return GetAttributeValue("sdkmessageid"); + } + set + { + OnPropertyChanging("SdkMessageId"); + SetAttributeValue("sdkmessageid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("SdkMessageId"); + } + } + + [AttributeLogicalName("sdkmessageid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + SdkMessageId = value; + } + } + + /// + /// Unique identifier of the SDK message. + /// + [AttributeLogicalName("sdkmessageidunique")] + public Guid? SdkMessageIdUnique + { + get + { + return GetAttributeValue("sdkmessageidunique"); + } + } + + /// + /// Indicates whether the SDK message is a template. + /// + [AttributeLogicalName("template")] + public bool? Template + { + get + { + return GetAttributeValue("template"); + } + set + { + OnPropertyChanging("Template"); + SetAttributeValue("template", value); + OnPropertyChanged("Template"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("throttlesettings")] + public string ThrottleSettings + { + get + { + return GetAttributeValue("throttlesettings"); + } + } + + /// + /// Number that identifies a specific revision of the SDK message. + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/SdkMessageFilter.cs b/Ofscrm.PluginRegistration/Entities/SdkMessageFilter.cs new file mode 100644 index 0000000..192034b --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SdkMessageFilter.cs @@ -0,0 +1,300 @@ +using System; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Filter that defines which SDK messages are valid for each type of entity. + /// + [DataContract()] + [EntityLogicalName("sdkmessagefilter")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class SdkMessageFilter : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public SdkMessageFilter() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "sdkmessagefilter"; + + public const int EntityTypeCode = 4607; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Identifies where a method will be exposed. 0 - Server, 1 - Client, 2 - both. + /// + [AttributeLogicalName("availability")] + public int? Availability + { + get + { + return GetAttributeValue("availability"); + } + set + { + OnPropertyChanging("Availability"); + SetAttributeValue("availability", value); + OnPropertyChanged("Availability"); + } + } + + /// + /// Unique identifier of the user who created the SDK message filter. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the SDK message filter was created. + /// + [AttributeLogicalName("createdon")] + public System.DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the sdkmessagefilter. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Customization level of the SDK message filter. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Indicates whether a custom SDK message processing step is allowed. + /// + [AttributeLogicalName("iscustomprocessingstepallowed")] + public bool? IsCustomProcessingStepAllowed + { + get + { + return GetAttributeValue("iscustomprocessingstepallowed"); + } + set + { + OnPropertyChanging("IsCustomProcessingStepAllowed"); + SetAttributeValue("iscustomprocessingstepallowed", value); + OnPropertyChanged("IsCustomProcessingStepAllowed"); + } + } + + /// + /// Indicates whether the filter should be visible. + /// + [AttributeLogicalName("isvisible")] + public bool? IsVisible + { + get + { + return GetAttributeValue("isvisible"); + } + } + + /// + /// Unique identifier of the user who last modified the SDK message filter. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the SDK message filter was last modified. + /// + [AttributeLogicalName("modifiedon")] + public System.DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the sdkmessagefilter. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Unique identifier of the organization with which the SDK message filter is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// Type of entity with which the SDK message filter is primarily associated. + /// + [AttributeLogicalName("primaryobjecttypecode")] + public string PrimaryObjectTypeCode + { + get + { + return GetAttributeValue("primaryobjecttypecode"); + } + } + + /// + /// Unique identifier of the SDK message filter entity. + /// + [AttributeLogicalName("sdkmessagefilterid")] + public Guid? SdkMessageFilterId + { + get + { + return GetAttributeValue("sdkmessagefilterid"); + } + set + { + OnPropertyChanging("SdkMessageFilterId"); + SetAttributeValue("sdkmessagefilterid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("SdkMessageFilterId"); + } + } + + [AttributeLogicalName("sdkmessagefilterid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + SdkMessageFilterId = value; + } + } + + /// + /// Unique identifier of the SDK message filter. + /// + [AttributeLogicalName("sdkmessagefilteridunique")] + public Guid? SdkMessageFilterIdUnique + { + get + { + return GetAttributeValue("sdkmessagefilteridunique"); + } + } + + /// + /// Unique identifier of the related SDK message. + /// + [AttributeLogicalName("sdkmessageid")] + public EntityReference SdkMessageId + { + get + { + return GetAttributeValue("sdkmessageid"); + } + set + { + OnPropertyChanging("SdkMessageId"); + SetAttributeValue("sdkmessageid", value); + OnPropertyChanged("SdkMessageId"); + } + } + + /// + /// Type of entity with which the SDK message filter is secondarily associated. + /// + [AttributeLogicalName("secondaryobjecttypecode")] + public string SecondaryObjectTypeCode + { + get + { + return GetAttributeValue("secondaryobjecttypecode"); + } + } + + /// + /// + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStep.cs b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStep.cs new file mode 100644 index 0000000..4b638b3 --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStep.cs @@ -0,0 +1,660 @@ +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Stage in the execution pipeline that a plug-in is to execute. + /// + [DataContract()] + [EntityLogicalName("sdkmessageprocessingstep")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class SdkMessageProcessingStep : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public SdkMessageProcessingStep() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "sdkmessageprocessingstep"; + + public const int EntityTypeCode = 4608; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Indicates whether the asynchronous system job is automatically deleted on completion. + /// + [AttributeLogicalName("asyncautodelete")] + public bool? AsyncAutoDelete + { + get + { + return GetAttributeValue("asyncautodelete"); + } + set + { + OnPropertyChanging("AsyncAutoDelete"); + SetAttributeValue("asyncautodelete", value); + OnPropertyChanged("AsyncAutoDelete"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("componentstate")] + public OptionSetValue ComponentState + { + get + { + return GetAttributeValue("componentstate"); + } + } + + /// + /// Step-specific configuration for the plug-in type. Passed to the plug-in constructor at run time. + /// + [AttributeLogicalName("configuration")] + public string Configuration + { + get + { + return GetAttributeValue("configuration"); + } + set + { + OnPropertyChanging("Configuration"); + SetAttributeValue("configuration", value); + OnPropertyChanged("Configuration"); + } + } + + /// + /// Unique identifier of the user who created the SDK message processing step. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the SDK message processing step was created. + /// + [AttributeLogicalName("createdon")] + public DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the sdkmessageprocessingstep. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Customization level of the SDK message processing step. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Description of the SDK message processing step. + /// + [AttributeLogicalName("description")] + public string Description + { + get + { + return GetAttributeValue("description"); + } + set + { + OnPropertyChanging("Description"); + SetAttributeValue("description", value); + OnPropertyChanged("Description"); + } + } + + /// + /// Unique identifier of the associated event handler. + /// + [AttributeLogicalName("eventhandler")] + public EntityReference EventHandler + { + get + { + return GetAttributeValue("eventhandler"); + } + set + { + OnPropertyChanging("EventHandler"); + SetAttributeValue("eventhandler", value); + OnPropertyChanged("EventHandler"); + } + } + + /// + /// Comma-separated list of attributes. If at least one of these attributes is modified, the plug-in should execute. + /// + [AttributeLogicalName("filteringattributes")] + public string FilteringAttributes + { + get + { + return GetAttributeValue("filteringattributes"); + } + set + { + OnPropertyChanging("FilteringAttributes"); + SetAttributeValue("filteringattributes", value); + OnPropertyChanged("FilteringAttributes"); + } + } + + /// + /// Unique identifier of the user to impersonate context when step is executed. + /// + [AttributeLogicalName("impersonatinguserid")] + public EntityReference ImpersonatingUserId + { + get + { + return GetAttributeValue("impersonatinguserid"); + } + set + { + OnPropertyChanging("ImpersonatingUserId"); + SetAttributeValue("impersonatinguserid", value); + OnPropertyChanged("ImpersonatingUserId"); + } + } + + /// + /// Identifies if a plug-in should be executed from a parent pipeline, a child pipeline, or both. + /// + [AttributeLogicalName("invocationsource")] + [Obsolete()] + public OptionSetValue InvocationSource + { + get + { + return GetAttributeValue("invocationsource"); + } + set + { + OnPropertyChanging("InvocationSource"); + SetAttributeValue("invocationsource", value); + OnPropertyChanged("InvocationSource"); + } + } + + /// + /// Information that specifies whether this component can be customized. + /// + [AttributeLogicalName("iscustomizable")] + public BooleanManagedProperty IsCustomizable + { + get + { + return GetAttributeValue("iscustomizable"); + } + set + { + OnPropertyChanging("IsCustomizable"); + SetAttributeValue("iscustomizable", value); + OnPropertyChanged("IsCustomizable"); + } + } + + /// + /// Information that specifies whether this component should be hidden. + /// + [AttributeLogicalName("ishidden")] + public BooleanManagedProperty IsHidden + { + get + { + return GetAttributeValue("ishidden"); + } + set + { + OnPropertyChanging("IsHidden"); + SetAttributeValue("ishidden", value); + OnPropertyChanged("IsHidden"); + } + } + + /// + /// Information that specifies whether this component is managed. + /// + [AttributeLogicalName("ismanaged")] + public bool? IsManaged + { + get + { + return GetAttributeValue("ismanaged"); + } + } + + /// + /// Run-time mode of execution, for example, synchronous or asynchronous. + /// + [AttributeLogicalName("mode")] + public OptionSetValue Mode + { + get + { + return GetAttributeValue("mode"); + } + set + { + OnPropertyChanging("Mode"); + SetAttributeValue("mode", value); + OnPropertyChanged("Mode"); + } + } + + /// + /// Unique identifier of the user who last modified the SDK message processing step. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the SDK message processing step was last modified. + /// + [AttributeLogicalName("modifiedon")] + public DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the sdkmessageprocessingstep. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Name of SdkMessage processing step. + /// + [AttributeLogicalName("name")] + public string Name + { + get + { + return GetAttributeValue("name"); + } + set + { + OnPropertyChanging("Name"); + SetAttributeValue("name", value); + OnPropertyChanged("Name"); + } + } + + /// + /// Unique identifier of the organization with which the SDK message processing step is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("overwritetime")] + public DateTime? OverwriteTime + { + get + { + return GetAttributeValue("overwritetime"); + } + } + + /// + /// Unique identifier of the plug-in type associated with the step. + /// + [AttributeLogicalName("plugintypeid")] + [Obsolete()] + public EntityReference PluginTypeId + { + get + { + return GetAttributeValue("plugintypeid"); + } + set + { + OnPropertyChanging("PluginTypeId"); + SetAttributeValue("plugintypeid", value); + OnPropertyChanged("PluginTypeId"); + } + } + + /// + /// Processing order within the stage. + /// + [AttributeLogicalName("rank")] + public int? Rank + { + get + { + return GetAttributeValue("rank"); + } + set + { + OnPropertyChanging("Rank"); + SetAttributeValue("rank", value); + OnPropertyChanged("Rank"); + } + } + + /// + /// Unique identifier of the SDK message filter. + /// + [AttributeLogicalName("sdkmessagefilterid")] + public EntityReference SdkMessageFilterId + { + get + { + return GetAttributeValue("sdkmessagefilterid"); + } + set + { + OnPropertyChanging("SdkMessageFilterId"); + SetAttributeValue("sdkmessagefilterid", value); + OnPropertyChanged("SdkMessageFilterId"); + } + } + + /// + /// Unique identifier of the SDK message. + /// + [AttributeLogicalName("sdkmessageid")] + public EntityReference SdkMessageId + { + get + { + return GetAttributeValue("sdkmessageid"); + } + set + { + OnPropertyChanging("SdkMessageId"); + SetAttributeValue("sdkmessageid", value); + OnPropertyChanged("SdkMessageId"); + } + } + + /// + /// Unique identifier of the SDK message processing step entity. + /// + [AttributeLogicalName("sdkmessageprocessingstepid")] + public Guid? SdkMessageProcessingStepId + { + get + { + return GetAttributeValue("sdkmessageprocessingstepid"); + } + set + { + OnPropertyChanging("SdkMessageProcessingStepId"); + SetAttributeValue("sdkmessageprocessingstepid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("SdkMessageProcessingStepId"); + } + } + + [AttributeLogicalName("sdkmessageprocessingstepid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + SdkMessageProcessingStepId = value; + } + } + + /// + /// Unique identifier of the SDK message processing step. + /// + [AttributeLogicalName("sdkmessageprocessingstepidunique")] + public Guid? SdkMessageProcessingStepIdUnique + { + get + { + return GetAttributeValue("sdkmessageprocessingstepidunique"); + } + } + + /// + /// Unique identifier of the Sdk message processing step secure configuration. + /// + [AttributeLogicalName("sdkmessageprocessingstepsecureconfigid")] + public EntityReference SdkMessageProcessingStepSecureConfigId + { + get + { + return GetAttributeValue("sdkmessageprocessingstepsecureconfigid"); + } + set + { + OnPropertyChanging("SdkMessageProcessingStepSecureConfigId"); + SetAttributeValue("sdkmessageprocessingstepsecureconfigid", value); + OnPropertyChanged("SdkMessageProcessingStepSecureConfigId"); + } + } + + /// + /// Unique identifier of the associated solution. + /// + [AttributeLogicalName("solutionid")] + public Guid? SolutionId + { + get + { + return GetAttributeValue("solutionid"); + } + } + + /// + /// Stage in the execution pipeline that the SDK message processing step is in. + /// + [AttributeLogicalName("stage")] + public OptionSetValue Stage + { + get + { + return GetAttributeValue("stage"); + } + set + { + OnPropertyChanging("Stage"); + SetAttributeValue("stage", value); + OnPropertyChanged("Stage"); + } + } + + /// + /// Status of the SDK message processing step. + /// + [AttributeLogicalName("statecode")] + public SdkMessageProcessingStepState? StateCode + { + get + { + OptionSetValue optionSet = GetAttributeValue("statecode"); + if ((optionSet != null)) + { + return ((SdkMessageProcessingStepState)(System.Enum.ToObject(typeof(SdkMessageProcessingStepState), optionSet.Value))); + } + else + { + return null; + } + } + } + + /// + /// Reason for the status of the SDK message processing step. + /// + [AttributeLogicalName("statuscode")] + public OptionSetValue StatusCode + { + get + { + return GetAttributeValue("statuscode"); + } + set + { + OnPropertyChanging("StatusCode"); + SetAttributeValue("statuscode", value); + OnPropertyChanged("StatusCode"); + } + } + + /// + /// Deployment that the SDK message processing step should be executed on; server, client, or both. + /// + [AttributeLogicalName("supporteddeployment")] + public OptionSetValue SupportedDeployment + { + get + { + return GetAttributeValue("supporteddeployment"); + } + set + { + OnPropertyChanging("SupportedDeployment"); + SetAttributeValue("supporteddeployment", value); + OnPropertyChanged("SupportedDeployment"); + } + } + + /// + /// Number that identifies a specific revision of the SDK message processing step. + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + + /// + /// 1:N sdkmessageprocessingstepid_sdkmessageprocessingstepimage + /// + [RelationshipSchemaName("sdkmessageprocessingstepid_sdkmessageprocessingstepimage")] + public IEnumerable sdkmessageprocessingstepid_sdkmessageprocessingstepimage + { + get + { + return GetRelatedEntities("sdkmessageprocessingstepid_sdkmessageprocessingstepimage", null); + } + set + { + OnPropertyChanging("sdkmessageprocessingstepid_sdkmessageprocessingstepimage"); + SetRelatedEntities("sdkmessageprocessingstepid_sdkmessageprocessingstepimage", null, value); + OnPropertyChanged("sdkmessageprocessingstepid_sdkmessageprocessingstepimage"); + } + } + + /// + /// N:1 sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep + /// + [AttributeLogicalName("sdkmessageprocessingstepsecureconfigid")] + [RelationshipSchemaName("sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep")] + public SdkMessageProcessingStepSecureConfig sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep + { + get + { + return GetRelatedEntity("sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep", null); + } + set + { + OnPropertyChanging("sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep"); + SetRelatedEntity("sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep", null, value); + OnPropertyChanged("sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepImage.cs b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepImage.cs new file mode 100644 index 0000000..cd22ca5 --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepImage.cs @@ -0,0 +1,420 @@ +using System; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Copy of an entity's attributes before or after the core system operation. + /// + [DataContract()] + [EntityLogicalName("sdkmessageprocessingstepimage")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class SdkMessageProcessingStepImage : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public SdkMessageProcessingStepImage() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "sdkmessageprocessingstepimage"; + + public const int EntityTypeCode = 4615; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Comma-separated list of attributes that are to be passed into the SDK message processing step image. + /// + [AttributeLogicalName("attributes")] + public string Attributes1 + { + get + { + return GetAttributeValue("attributes"); + } + set + { + OnPropertyChanging("Attributes1"); + SetAttributeValue("attributes", value); + OnPropertyChanged("Attributes1"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("componentstate")] + public OptionSetValue ComponentState + { + get + { + return GetAttributeValue("componentstate"); + } + } + + /// + /// Unique identifier of the user who created the SDK message processing step image. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the SDK message processing step image was created. + /// + [AttributeLogicalName("createdon")] + public DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the sdkmessageprocessingstepimage. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Customization level of the SDK message processing step image. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Description of the SDK message processing step image. + /// + [AttributeLogicalName("description")] + public string Description + { + get + { + return GetAttributeValue("description"); + } + set + { + OnPropertyChanging("Description"); + SetAttributeValue("description", value); + OnPropertyChanged("Description"); + } + } + + /// + /// Key name used to access the pre-image or post-image property bags in a step. + /// + [AttributeLogicalName("entityalias")] + public string EntityAlias + { + get + { + return GetAttributeValue("entityalias"); + } + set + { + OnPropertyChanging("EntityAlias"); + SetAttributeValue("entityalias", value); + OnPropertyChanged("EntityAlias"); + } + } + + /// + /// Type of image requested. + /// + [AttributeLogicalName("imagetype")] + public OptionSetValue ImageType + { + get + { + return GetAttributeValue("imagetype"); + } + set + { + OnPropertyChanging("ImageType"); + SetAttributeValue("imagetype", value); + OnPropertyChanged("ImageType"); + } + } + + /// + /// Information that specifies whether this component can be customized. + /// + [AttributeLogicalName("iscustomizable")] + public BooleanManagedProperty IsCustomizable + { + get + { + return GetAttributeValue("iscustomizable"); + } + set + { + OnPropertyChanging("IsCustomizable"); + SetAttributeValue("iscustomizable", value); + OnPropertyChanged("IsCustomizable"); + } + } + + /// + /// + /// + [AttributeLogicalName("ismanaged")] + public bool? IsManaged + { + get + { + return GetAttributeValue("ismanaged"); + } + } + + /// + /// Name of the property on the Request message. + /// + [AttributeLogicalName("messagepropertyname")] + public string MessagePropertyName + { + get + { + return GetAttributeValue("messagepropertyname"); + } + set + { + OnPropertyChanging("MessagePropertyName"); + SetAttributeValue("messagepropertyname", value); + OnPropertyChanged("MessagePropertyName"); + } + } + + /// + /// Unique identifier of the user who last modified the SDK message processing step. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the SDK message processing step was last modified. + /// + [AttributeLogicalName("modifiedon")] + public DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the sdkmessageprocessingstepimage. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Name of SdkMessage processing step image. + /// + [AttributeLogicalName("name")] + public string Name + { + get + { + return GetAttributeValue("name"); + } + set + { + OnPropertyChanging("Name"); + SetAttributeValue("name", value); + OnPropertyChanged("Name"); + } + } + + /// + /// Unique identifier of the organization with which the SDK message processing step is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("overwritetime")] + public DateTime? OverwriteTime + { + get + { + return GetAttributeValue("overwritetime"); + } + } + + /// + /// Name of the related entity. + /// + [AttributeLogicalName("relatedattributename")] + public string RelatedAttributeName + { + get + { + return GetAttributeValue("relatedattributename"); + } + set + { + OnPropertyChanging("RelatedAttributeName"); + SetAttributeValue("relatedattributename", value); + OnPropertyChanged("RelatedAttributeName"); + } + } + + /// + /// Unique identifier of the SDK message processing step. + /// + [AttributeLogicalName("sdkmessageprocessingstepid")] + public EntityReference SdkMessageProcessingStepId + { + get + { + return GetAttributeValue("sdkmessageprocessingstepid"); + } + set + { + OnPropertyChanging("SdkMessageProcessingStepId"); + SetAttributeValue("sdkmessageprocessingstepid", value); + OnPropertyChanged("SdkMessageProcessingStepId"); + } + } + + /// + /// Unique identifier of the SDK message processing step image entity. + /// + [AttributeLogicalName("sdkmessageprocessingstepimageid")] + public Guid? SdkMessageProcessingStepImageId + { + get + { + return GetAttributeValue("sdkmessageprocessingstepimageid"); + } + set + { + OnPropertyChanging("SdkMessageProcessingStepImageId"); + SetAttributeValue("sdkmessageprocessingstepimageid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("SdkMessageProcessingStepImageId"); + } + } + + [AttributeLogicalName("sdkmessageprocessingstepimageid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + SdkMessageProcessingStepImageId = value; + } + } + + /// + /// Unique identifier of the SDK message processing step image. + /// + [AttributeLogicalName("sdkmessageprocessingstepimageidunique")] + public Guid? SdkMessageProcessingStepImageIdUnique + { + get + { + return GetAttributeValue("sdkmessageprocessingstepimageidunique"); + } + } + + /// + /// Unique identifier of the associated solution. + /// + [AttributeLogicalName("solutionid")] + public Guid? SolutionId + { + get + { + return GetAttributeValue("solutionid"); + } + } + + /// + /// Number that identifies a specific revision of the step image. + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepSecureConfig.cs b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepSecureConfig.cs new file mode 100644 index 0000000..0a294a5 --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepSecureConfig.cs @@ -0,0 +1,216 @@ +using System; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Non-public custom configuration that is passed to a plug-in's constructor. + /// + [DataContract()] + [EntityLogicalName("sdkmessageprocessingstepsecureconfig")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class SdkMessageProcessingStepSecureConfig : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public SdkMessageProcessingStepSecureConfig() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "sdkmessageprocessingstepsecureconfig"; + + public const int EntityTypeCode = 4616; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new System.ComponentModel.PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Unique identifier of the user who created the SDK message processing step. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the SDK message processing step was created. + /// + [AttributeLogicalName("createdon")] + public DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the sdkmessageprocessingstepsecureconfig. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Customization level of the SDK message processing step secure configuration. + /// + [AttributeLogicalName("customizationlevel")] + public int? CustomizationLevel + { + get + { + return GetAttributeValue("customizationlevel"); + } + } + + /// + /// Unique identifier of the user who last modified the SDK message processing step. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the SDK message processing step was last modified. + /// + [AttributeLogicalName("modifiedon")] + public DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the sdkmessageprocessingstepsecureconfig. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Unique identifier of the organization with which the SDK message processing step is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// Unique identifier of the SDK message processing step secure configuration. + /// + [AttributeLogicalName("sdkmessageprocessingstepsecureconfigid")] + public Guid? SdkMessageProcessingStepSecureConfigId + { + get + { + return GetAttributeValue("sdkmessageprocessingstepsecureconfigid"); + } + set + { + OnPropertyChanging("SdkMessageProcessingStepSecureConfigId"); + SetAttributeValue("sdkmessageprocessingstepsecureconfigid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("SdkMessageProcessingStepSecureConfigId"); + } + } + + [AttributeLogicalName("sdkmessageprocessingstepsecureconfigid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + SdkMessageProcessingStepSecureConfigId = value; + } + } + + /// + /// Unique identifier of the SDK message processing step. + /// + [AttributeLogicalName("sdkmessageprocessingstepsecureconfigidunique")] + public Guid? SdkMessageProcessingStepSecureConfigIdUnique + { + get + { + return GetAttributeValue("sdkmessageprocessingstepsecureconfigidunique"); + } + } + + /// + /// Secure step-specific configuration for the plug-in type that is passed to the plug-in's constructor at run time. + /// + [AttributeLogicalName("secureconfig")] + public string SecureConfig + { + get + { + return GetAttributeValue("secureconfig"); + } + set + { + OnPropertyChanging("SecureConfig"); + SetAttributeValue("secureconfig", value); + OnPropertyChanged("SecureConfig"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepState.cs b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepState.cs new file mode 100644 index 0000000..c9809ec --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SdkMessageProcessingStepState.cs @@ -0,0 +1,17 @@ +using System.CodeDom.Compiler; +using System.Runtime.Serialization; + +namespace Ofscrm.PluginRegistration.Entities +{ + [DataContract()] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public enum SdkMessageProcessingStepState + { + + [EnumMember()] + Enabled = 0, + + [EnumMember()] + Disabled = 1, + } +} diff --git a/Ofscrm.PluginRegistration/Entities/ServiceEndpoint.cs b/Ofscrm.PluginRegistration/Entities/ServiceEndpoint.cs new file mode 100644 index 0000000..f13a5bd --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/ServiceEndpoint.cs @@ -0,0 +1,377 @@ +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Service endpoint that can be contacted. + /// + [DataContract()] + [EntityLogicalName("serviceendpoint")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class ServiceEndpoint : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public ServiceEndpoint() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "serviceendpoint"; + + public const int EntityTypeCode = 4618; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("componentstate")] + public OptionSetValue ComponentState + { + get + { + return GetAttributeValue("componentstate"); + } + } + + /// + /// Connection mode to contact the service endpoint. + /// + [AttributeLogicalName("connectionmode")] + public OptionSetValue ConnectionMode + { + get + { + return GetAttributeValue("connectionmode"); + } + set + { + OnPropertyChanging("ConnectionMode"); + SetAttributeValue("connectionmode", value); + OnPropertyChanged("ConnectionMode"); + } + } + + /// + /// Type of the endpoint contract. + /// + [AttributeLogicalName("contract")] + public OptionSetValue Contract + { + get + { + return GetAttributeValue("contract"); + } + set + { + OnPropertyChanging("Contract"); + SetAttributeValue("contract", value); + OnPropertyChanged("Contract"); + } + } + + /// + /// Unique identifier of the user who created the service endpoint. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the service endpoint was created. + /// + [AttributeLogicalName("createdon")] + public System.DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the service endpoint. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Description of the service endpoint. + /// + [AttributeLogicalName("description")] + public string Description + { + get + { + return GetAttributeValue("description"); + } + set + { + OnPropertyChanging("Description"); + SetAttributeValue("description", value); + OnPropertyChanged("Description"); + } + } + + /// + /// Information that specifies whether this component can be customized. + /// + [AttributeLogicalName("iscustomizable")] + public BooleanManagedProperty IsCustomizable + { + get + { + return GetAttributeValue("iscustomizable"); + } + set + { + OnPropertyChanging("IsCustomizable"); + SetAttributeValue("iscustomizable", value); + OnPropertyChanged("IsCustomizable"); + } + } + + /// + /// Information that specifies whether this component is managed. + /// + [AttributeLogicalName("ismanaged")] + public bool? IsManaged + { + get + { + return GetAttributeValue("ismanaged"); + } + } + + /// + /// Unique identifier of the user who last modified the service endpoint. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the service endpoint was last modified. + /// + [AttributeLogicalName("modifiedon")] + public System.DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who modified the service endpoint. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Name of Service end point. + /// + [AttributeLogicalName("name")] + public string Name + { + get + { + return GetAttributeValue("name"); + } + set + { + OnPropertyChanging("Name"); + SetAttributeValue("name", value); + OnPropertyChanged("Name"); + } + } + + /// + /// Unique identifier of the organization with which the service endpoint is associated. + /// + [AttributeLogicalName("organizationid")] + public EntityReference OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("overwritetime")] + public System.DateTime? OverwriteTime + { + get + { + return GetAttributeValue("overwritetime"); + } + } + + /// + /// Path to the service endpoint. + /// + [AttributeLogicalName("path")] + public string Path + { + get + { + return GetAttributeValue("path"); + } + set + { + OnPropertyChanging("Path"); + SetAttributeValue("path", value); + OnPropertyChanged("Path"); + } + } + + /// + /// Unique identifier of the service endpoint. + /// + [AttributeLogicalName("serviceendpointid")] + public System.Guid? ServiceEndpointId + { + get + { + return GetAttributeValue("serviceendpointid"); + } + set + { + OnPropertyChanging("ServiceEndpointId"); + SetAttributeValue("serviceendpointid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = System.Guid.Empty; + } + OnPropertyChanged("ServiceEndpointId"); + } + } + + [AttributeLogicalName("serviceendpointid")] + public override System.Guid Id + { + get + { + return base.Id; + } + set + { + ServiceEndpointId = value; + } + } + + /// + /// Unique identifier of the service endpoint. + /// + [AttributeLogicalName("serviceendpointidunique")] + public System.Guid? ServiceEndpointIdUnique + { + get + { + return GetAttributeValue("serviceendpointidunique"); + } + } + + /// + /// Unique identifier of the associated solution. + /// + [AttributeLogicalName("solutionid")] + public System.Guid? SolutionId + { + get + { + return GetAttributeValue("solutionid"); + } + } + + /// + /// Namespace of the App Fabric solution. + /// + [AttributeLogicalName("solutionnamespace")] + public string SolutionNamespace + { + get + { + return GetAttributeValue("solutionnamespace"); + } + set + { + OnPropertyChanging("SolutionNamespace"); + SetAttributeValue("solutionnamespace", value); + OnPropertyChanged("SolutionNamespace"); + } + } + + /// + /// Additional user claim value type. + /// + [AttributeLogicalName("userclaim")] + public OptionSetValue UserClaim + { + get + { + return GetAttributeValue("userclaim"); + } + set + { + OnPropertyChanging("UserClaim"); + SetAttributeValue("userclaim", value); + OnPropertyChanged("UserClaim"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/SystemUser.cs b/Ofscrm.PluginRegistration/Entities/SystemUser.cs new file mode 100644 index 0000000..c132936 --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/SystemUser.cs @@ -0,0 +1,1878 @@ +using System; +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Runtime.Serialization; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; + +namespace Ofscrm.PluginRegistration.Entities +{ + /// + /// Person with access to the Microsoft CRM system and who owns objects in the Microsoft CRM database. + /// + [DataContract()] + [EntityLogicalName("systemuser")] + [GeneratedCode("CrmSvcUtil", "5.0.9689.1985")] + public partial class SystemUser : Entity, INotifyPropertyChanging, INotifyPropertyChanged + { + + /// + /// Default Constructor. + /// + public SystemUser() : + base(EntityLogicalName) + { + } + + public const string EntityLogicalName = "systemuser"; + + public const int EntityTypeCode = 8; + + public event PropertyChangedEventHandler PropertyChanged; + + public event PropertyChangingEventHandler PropertyChanging; + + private void OnPropertyChanged(string propertyName) + { + if ((PropertyChanged != null)) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void OnPropertyChanging(string propertyName) + { + if ((PropertyChanging != null)) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Type of user. + /// + [AttributeLogicalName("accessmode")] + public OptionSetValue AccessMode + { + get + { + return GetAttributeValue("accessmode"); + } + set + { + OnPropertyChanging("AccessMode"); + SetAttributeValue("accessmode", value); + OnPropertyChanged("AccessMode"); + } + } + + /// + /// Unique identifier for address 1. + /// + [AttributeLogicalName("address1_addressid")] + public Guid? Address1_AddressId + { + get + { + return GetAttributeValue("address1_addressid"); + } + set + { + OnPropertyChanging("Address1_AddressId"); + SetAttributeValue("address1_addressid", value); + OnPropertyChanged("Address1_AddressId"); + } + } + + /// + /// Type of address for address 1, such as billing, shipping, or primary address. + /// + [AttributeLogicalName("address1_addresstypecode")] + public OptionSetValue Address1_AddressTypeCode + { + get + { + return GetAttributeValue("address1_addresstypecode"); + } + set + { + OnPropertyChanging("Address1_AddressTypeCode"); + SetAttributeValue("address1_addresstypecode", value); + OnPropertyChanged("Address1_AddressTypeCode"); + } + } + + /// + /// City name for address 1. + /// + [AttributeLogicalName("address1_city")] + public string Address1_City + { + get + { + return GetAttributeValue("address1_city"); + } + set + { + OnPropertyChanging("Address1_City"); + SetAttributeValue("address1_city", value); + OnPropertyChanged("Address1_City"); + } + } + + /// + /// Country/region name in address 1. + /// + [AttributeLogicalName("address1_country")] + public string Address1_Country + { + get + { + return GetAttributeValue("address1_country"); + } + set + { + OnPropertyChanging("Address1_Country"); + SetAttributeValue("address1_country", value); + OnPropertyChanged("Address1_Country"); + } + } + + /// + /// County name for address 1. + /// + [AttributeLogicalName("address1_county")] + public string Address1_County + { + get + { + return GetAttributeValue("address1_county"); + } + set + { + OnPropertyChanging("Address1_County"); + SetAttributeValue("address1_county", value); + OnPropertyChanged("Address1_County"); + } + } + + /// + /// Fax number for address 1. + /// + [AttributeLogicalName("address1_fax")] + public string Address1_Fax + { + get + { + return GetAttributeValue("address1_fax"); + } + set + { + OnPropertyChanging("Address1_Fax"); + SetAttributeValue("address1_fax", value); + OnPropertyChanged("Address1_Fax"); + } + } + + /// + /// Latitude for address 1. + /// + [AttributeLogicalName("address1_latitude")] + public double? Address1_Latitude + { + get + { + return GetAttributeValue("address1_latitude"); + } + set + { + OnPropertyChanging("Address1_Latitude"); + SetAttributeValue("address1_latitude", value); + OnPropertyChanged("Address1_Latitude"); + } + } + + /// + /// First line for entering address 1 information. + /// + [AttributeLogicalName("address1_line1")] + public string Address1_Line1 + { + get + { + return GetAttributeValue("address1_line1"); + } + set + { + OnPropertyChanging("Address1_Line1"); + SetAttributeValue("address1_line1", value); + OnPropertyChanged("Address1_Line1"); + } + } + + /// + /// Second line for entering address 1 information. + /// + [AttributeLogicalName("address1_line2")] + public string Address1_Line2 + { + get + { + return GetAttributeValue("address1_line2"); + } + set + { + OnPropertyChanging("Address1_Line2"); + SetAttributeValue("address1_line2", value); + OnPropertyChanged("Address1_Line2"); + } + } + + /// + /// Third line for entering address 1 information. + /// + [AttributeLogicalName("address1_line3")] + public string Address1_Line3 + { + get + { + return GetAttributeValue("address1_line3"); + } + set + { + OnPropertyChanging("Address1_Line3"); + SetAttributeValue("address1_line3", value); + OnPropertyChanged("Address1_Line3"); + } + } + + /// + /// Longitude for address 1. + /// + [AttributeLogicalName("address1_longitude")] + public double? Address1_Longitude + { + get + { + return GetAttributeValue("address1_longitude"); + } + set + { + OnPropertyChanging("Address1_Longitude"); + SetAttributeValue("address1_longitude", value); + OnPropertyChanged("Address1_Longitude"); + } + } + + /// + /// Name to enter for address 1. + /// + [AttributeLogicalName("address1_name")] + public string Address1_Name + { + get + { + return GetAttributeValue("address1_name"); + } + set + { + OnPropertyChanging("Address1_Name"); + SetAttributeValue("address1_name", value); + OnPropertyChanged("Address1_Name"); + } + } + + /// + /// ZIP Code or postal code for address 1. + /// + [AttributeLogicalName("address1_postalcode")] + public string Address1_PostalCode + { + get + { + return GetAttributeValue("address1_postalcode"); + } + set + { + OnPropertyChanging("Address1_PostalCode"); + SetAttributeValue("address1_postalcode", value); + OnPropertyChanged("Address1_PostalCode"); + } + } + + /// + /// Post office box number for address 1. + /// + [AttributeLogicalName("address1_postofficebox")] + public string Address1_PostOfficeBox + { + get + { + return GetAttributeValue("address1_postofficebox"); + } + set + { + OnPropertyChanging("Address1_PostOfficeBox"); + SetAttributeValue("address1_postofficebox", value); + OnPropertyChanged("Address1_PostOfficeBox"); + } + } + + /// + /// Method of shipment for address 1. + /// + [AttributeLogicalName("address1_shippingmethodcode")] + public OptionSetValue Address1_ShippingMethodCode + { + get + { + return GetAttributeValue("address1_shippingmethodcode"); + } + set + { + OnPropertyChanging("Address1_ShippingMethodCode"); + SetAttributeValue("address1_shippingmethodcode", value); + OnPropertyChanged("Address1_ShippingMethodCode"); + } + } + + /// + /// State or province for address 1. + /// + [AttributeLogicalName("address1_stateorprovince")] + public string Address1_StateOrProvince + { + get + { + return GetAttributeValue("address1_stateorprovince"); + } + set + { + OnPropertyChanging("Address1_StateOrProvince"); + SetAttributeValue("address1_stateorprovince", value); + OnPropertyChanged("Address1_StateOrProvince"); + } + } + + /// + /// First telephone number associated with address 1. + /// + [AttributeLogicalName("address1_telephone1")] + public string Address1_Telephone1 + { + get + { + return GetAttributeValue("address1_telephone1"); + } + set + { + OnPropertyChanging("Address1_Telephone1"); + SetAttributeValue("address1_telephone1", value); + OnPropertyChanged("Address1_Telephone1"); + } + } + + /// + /// Second telephone number associated with address 1. + /// + [AttributeLogicalName("address1_telephone2")] + public string Address1_Telephone2 + { + get + { + return GetAttributeValue("address1_telephone2"); + } + set + { + OnPropertyChanging("Address1_Telephone2"); + SetAttributeValue("address1_telephone2", value); + OnPropertyChanged("Address1_Telephone2"); + } + } + + /// + /// Third telephone number associated with address 1. + /// + [AttributeLogicalName("address1_telephone3")] + public string Address1_Telephone3 + { + get + { + return GetAttributeValue("address1_telephone3"); + } + set + { + OnPropertyChanging("Address1_Telephone3"); + SetAttributeValue("address1_telephone3", value); + OnPropertyChanged("Address1_Telephone3"); + } + } + + /// + /// United Parcel Service (UPS) zone for address 1. + /// + [AttributeLogicalName("address1_upszone")] + public string Address1_UPSZone + { + get + { + return GetAttributeValue("address1_upszone"); + } + set + { + OnPropertyChanging("Address1_UPSZone"); + SetAttributeValue("address1_upszone", value); + OnPropertyChanged("Address1_UPSZone"); + } + } + + /// + /// UTC offset for address 1. This is the difference between local time and standard Coordinated Universal Time. + /// + [AttributeLogicalName("address1_utcoffset")] + public int? Address1_UTCOffset + { + get + { + return GetAttributeValue("address1_utcoffset"); + } + set + { + OnPropertyChanging("Address1_UTCOffset"); + SetAttributeValue("address1_utcoffset", value); + OnPropertyChanged("Address1_UTCOffset"); + } + } + + /// + /// Unique identifier for address 2. + /// + [AttributeLogicalName("address2_addressid")] + public Guid? Address2_AddressId + { + get + { + return GetAttributeValue("address2_addressid"); + } + set + { + OnPropertyChanging("Address2_AddressId"); + SetAttributeValue("address2_addressid", value); + OnPropertyChanged("Address2_AddressId"); + } + } + + /// + /// Type of address for address 2, such as billing, shipping, or primary address. + /// + [AttributeLogicalName("address2_addresstypecode")] + public OptionSetValue Address2_AddressTypeCode + { + get + { + return GetAttributeValue("address2_addresstypecode"); + } + set + { + OnPropertyChanging("Address2_AddressTypeCode"); + SetAttributeValue("address2_addresstypecode", value); + OnPropertyChanged("Address2_AddressTypeCode"); + } + } + + /// + /// City name for address 2. + /// + [AttributeLogicalName("address2_city")] + public string Address2_City + { + get + { + return GetAttributeValue("address2_city"); + } + set + { + OnPropertyChanging("Address2_City"); + SetAttributeValue("address2_city", value); + OnPropertyChanged("Address2_City"); + } + } + + /// + /// Country/region name in address 2. + /// + [AttributeLogicalName("address2_country")] + public string Address2_Country + { + get + { + return GetAttributeValue("address2_country"); + } + set + { + OnPropertyChanging("Address2_Country"); + SetAttributeValue("address2_country", value); + OnPropertyChanged("Address2_Country"); + } + } + + /// + /// County name for address 2. + /// + [AttributeLogicalName("address2_county")] + public string Address2_County + { + get + { + return GetAttributeValue("address2_county"); + } + set + { + OnPropertyChanging("Address2_County"); + SetAttributeValue("address2_county", value); + OnPropertyChanged("Address2_County"); + } + } + + /// + /// Fax number for address 2. + /// + [AttributeLogicalName("address2_fax")] + public string Address2_Fax + { + get + { + return GetAttributeValue("address2_fax"); + } + set + { + OnPropertyChanging("Address2_Fax"); + SetAttributeValue("address2_fax", value); + OnPropertyChanged("Address2_Fax"); + } + } + + /// + /// Latitude for address 2. + /// + [AttributeLogicalName("address2_latitude")] + public double? Address2_Latitude + { + get + { + return GetAttributeValue("address2_latitude"); + } + set + { + OnPropertyChanging("Address2_Latitude"); + SetAttributeValue("address2_latitude", value); + OnPropertyChanged("Address2_Latitude"); + } + } + + /// + /// First line for entering address 2 information. + /// + [AttributeLogicalName("address2_line1")] + public string Address2_Line1 + { + get + { + return GetAttributeValue("address2_line1"); + } + set + { + OnPropertyChanging("Address2_Line1"); + SetAttributeValue("address2_line1", value); + OnPropertyChanged("Address2_Line1"); + } + } + + /// + /// Second line for entering address 2 information. + /// + [AttributeLogicalName("address2_line2")] + public string Address2_Line2 + { + get + { + return GetAttributeValue("address2_line2"); + } + set + { + OnPropertyChanging("Address2_Line2"); + SetAttributeValue("address2_line2", value); + OnPropertyChanged("Address2_Line2"); + } + } + + /// + /// Third line for entering address 2 information. + /// + [AttributeLogicalName("address2_line3")] + public string Address2_Line3 + { + get + { + return GetAttributeValue("address2_line3"); + } + set + { + OnPropertyChanging("Address2_Line3"); + SetAttributeValue("address2_line3", value); + OnPropertyChanged("Address2_Line3"); + } + } + + /// + /// Longitude for address 2. + /// + [AttributeLogicalName("address2_longitude")] + public double? Address2_Longitude + { + get + { + return GetAttributeValue("address2_longitude"); + } + set + { + OnPropertyChanging("Address2_Longitude"); + SetAttributeValue("address2_longitude", value); + OnPropertyChanged("Address2_Longitude"); + } + } + + /// + /// Name to enter for address 2. + /// + [AttributeLogicalName("address2_name")] + public string Address2_Name + { + get + { + return GetAttributeValue("address2_name"); + } + set + { + OnPropertyChanging("Address2_Name"); + SetAttributeValue("address2_name", value); + OnPropertyChanged("Address2_Name"); + } + } + + /// + /// ZIP Code or postal code for address 2. + /// + [AttributeLogicalName("address2_postalcode")] + public string Address2_PostalCode + { + get + { + return GetAttributeValue("address2_postalcode"); + } + set + { + OnPropertyChanging("Address2_PostalCode"); + SetAttributeValue("address2_postalcode", value); + OnPropertyChanged("Address2_PostalCode"); + } + } + + /// + /// Post office box number for address 2. + /// + [AttributeLogicalName("address2_postofficebox")] + public string Address2_PostOfficeBox + { + get + { + return GetAttributeValue("address2_postofficebox"); + } + set + { + OnPropertyChanging("Address2_PostOfficeBox"); + SetAttributeValue("address2_postofficebox", value); + OnPropertyChanged("Address2_PostOfficeBox"); + } + } + + /// + /// Method of shipment for address 2. + /// + [AttributeLogicalName("address2_shippingmethodcode")] + public OptionSetValue Address2_ShippingMethodCode + { + get + { + return GetAttributeValue("address2_shippingmethodcode"); + } + set + { + OnPropertyChanging("Address2_ShippingMethodCode"); + SetAttributeValue("address2_shippingmethodcode", value); + OnPropertyChanged("Address2_ShippingMethodCode"); + } + } + + /// + /// State or province for address 2. + /// + [AttributeLogicalName("address2_stateorprovince")] + public string Address2_StateOrProvince + { + get + { + return GetAttributeValue("address2_stateorprovince"); + } + set + { + OnPropertyChanging("Address2_StateOrProvince"); + SetAttributeValue("address2_stateorprovince", value); + OnPropertyChanged("Address2_StateOrProvince"); + } + } + + /// + /// First telephone number associated with address 2. + /// + [AttributeLogicalName("address2_telephone1")] + public string Address2_Telephone1 + { + get + { + return GetAttributeValue("address2_telephone1"); + } + set + { + OnPropertyChanging("Address2_Telephone1"); + SetAttributeValue("address2_telephone1", value); + OnPropertyChanged("Address2_Telephone1"); + } + } + + /// + /// Second telephone number associated with address 2. + /// + [AttributeLogicalName("address2_telephone2")] + public string Address2_Telephone2 + { + get + { + return GetAttributeValue("address2_telephone2"); + } + set + { + OnPropertyChanging("Address2_Telephone2"); + SetAttributeValue("address2_telephone2", value); + OnPropertyChanged("Address2_Telephone2"); + } + } + + /// + /// Third telephone number associated with address 2. + /// + [AttributeLogicalName("address2_telephone3")] + public string Address2_Telephone3 + { + get + { + return GetAttributeValue("address2_telephone3"); + } + set + { + OnPropertyChanging("Address2_Telephone3"); + SetAttributeValue("address2_telephone3", value); + OnPropertyChanged("Address2_Telephone3"); + } + } + + /// + /// United Parcel Service (UPS) zone for address 2. + /// + [AttributeLogicalName("address2_upszone")] + public string Address2_UPSZone + { + get + { + return GetAttributeValue("address2_upszone"); + } + set + { + OnPropertyChanging("Address2_UPSZone"); + SetAttributeValue("address2_upszone", value); + OnPropertyChanged("Address2_UPSZone"); + } + } + + /// + /// UTC offset for address 2. This is the difference between local time and standard Coordinated Universal Time. + /// + [AttributeLogicalName("address2_utcoffset")] + public int? Address2_UTCOffset + { + get + { + return GetAttributeValue("address2_utcoffset"); + } + set + { + OnPropertyChanging("Address2_UTCOffset"); + SetAttributeValue("address2_utcoffset", value); + OnPropertyChanged("Address2_UTCOffset"); + } + } + + /// + /// Unique identifier of the business unit with which the user is associated. + /// + [AttributeLogicalName("businessunitid")] + public EntityReference BusinessUnitId + { + get + { + return GetAttributeValue("businessunitid"); + } + set + { + OnPropertyChanging("BusinessUnitId"); + SetAttributeValue("businessunitid", value); + OnPropertyChanged("BusinessUnitId"); + } + } + + /// + /// Fiscal calendar associated with the user. + /// + [AttributeLogicalName("calendarid")] + public EntityReference CalendarId + { + get + { + return GetAttributeValue("calendarid"); + } + set + { + OnPropertyChanging("CalendarId"); + SetAttributeValue("calendarid", value); + OnPropertyChanged("CalendarId"); + } + } + + /// + /// License type of user. + /// + [AttributeLogicalName("caltype")] + public OptionSetValue CALType + { + get + { + return GetAttributeValue("caltype"); + } + set + { + OnPropertyChanging("CALType"); + SetAttributeValue("caltype", value); + OnPropertyChanged("CALType"); + } + } + + /// + /// Unique identifier of the user who created the user. + /// + [AttributeLogicalName("createdby")] + public EntityReference CreatedBy + { + get + { + return GetAttributeValue("createdby"); + } + } + + /// + /// Date and time when the user was created. + /// + [AttributeLogicalName("createdon")] + public DateTime? CreatedOn + { + get + { + return GetAttributeValue("createdon"); + } + } + + /// + /// Unique identifier of the delegate user who created the systemuser. + /// + [AttributeLogicalName("createdonbehalfby")] + public EntityReference CreatedOnBehalfBy + { + get + { + return GetAttributeValue("createdonbehalfby"); + } + } + + /// + /// Indicates if default outlook filters have been populated. + /// + [AttributeLogicalName("defaultfilterspopulated")] + public bool? DefaultFiltersPopulated + { + get + { + return GetAttributeValue("defaultfilterspopulated"); + } + } + + /// + /// Reason for disabling the user. + /// + [AttributeLogicalName("disabledreason")] + public string DisabledReason + { + get + { + return GetAttributeValue("disabledreason"); + } + } + + /// + /// Whether to display the user in service views. + /// + [AttributeLogicalName("displayinserviceviews")] + public bool? DisplayInServiceViews + { + get + { + return GetAttributeValue("displayinserviceviews"); + } + set + { + OnPropertyChanging("DisplayInServiceViews"); + SetAttributeValue("displayinserviceviews", value); + OnPropertyChanged("DisplayInServiceViews"); + } + } + + /// + /// Active Directory domain of which the user is a member. + /// + [AttributeLogicalName("domainname")] + public string DomainName + { + get + { + return GetAttributeValue("domainname"); + } + set + { + OnPropertyChanging("DomainName"); + SetAttributeValue("domainname", value); + OnPropertyChanged("DomainName"); + } + } + + /// + /// Shows the status of the primary e-mail address. + /// + [AttributeLogicalName("emailrouteraccessapproval")] + public OptionSetValue EmailRouterAccessApproval + { + get + { + return GetAttributeValue("emailrouteraccessapproval"); + } + set + { + OnPropertyChanging("EmailRouterAccessApproval"); + SetAttributeValue("emailrouteraccessapproval", value); + OnPropertyChanged("EmailRouterAccessApproval"); + } + } + + /// + /// Employee identifier for the user. + /// + [AttributeLogicalName("employeeid")] + public string EmployeeId + { + get + { + return GetAttributeValue("employeeid"); + } + set + { + OnPropertyChanging("EmployeeId"); + SetAttributeValue("employeeid", value); + OnPropertyChanged("EmployeeId"); + } + } + + /// + /// Exchange rate for the currency associated with the systemuser with respect to the base currency. + /// + [AttributeLogicalName("exchangerate")] + public decimal? ExchangeRate + { + get + { + return GetAttributeValue>("exchangerate"); + } + } + + /// + /// First name of the user. + /// + [AttributeLogicalName("firstname")] + public string FirstName + { + get + { + return GetAttributeValue("firstname"); + } + set + { + OnPropertyChanging("FirstName"); + SetAttributeValue("firstname", value); + OnPropertyChanged("FirstName"); + } + } + + /// + /// Full name of the user. + /// + [AttributeLogicalName("fullname")] + public string FullName + { + get + { + return GetAttributeValue("fullname"); + } + } + + /// + /// Government identifier for the user. + /// + [AttributeLogicalName("governmentid")] + public string GovernmentId + { + get + { + return GetAttributeValue("governmentid"); + } + set + { + OnPropertyChanging("GovernmentId"); + SetAttributeValue("governmentid", value); + OnPropertyChanged("GovernmentId"); + } + } + + /// + /// Home phone number for the user. + /// + [AttributeLogicalName("homephone")] + public string HomePhone + { + get + { + return GetAttributeValue("homephone"); + } + set + { + OnPropertyChanging("HomePhone"); + SetAttributeValue("homephone", value); + OnPropertyChanged("HomePhone"); + } + } + + /// + /// Unique identifier of the data import or data migration that created this record. + /// + [AttributeLogicalName("importsequencenumber")] + public int? ImportSequenceNumber + { + get + { + return GetAttributeValue("importsequencenumber"); + } + set + { + OnPropertyChanging("ImportSequenceNumber"); + SetAttributeValue("importsequencenumber", value); + OnPropertyChanged("ImportSequenceNumber"); + } + } + + /// + /// Incoming e-mail delivery method for the user. + /// + [AttributeLogicalName("incomingemaildeliverymethod")] + public OptionSetValue IncomingEmailDeliveryMethod + { + get + { + return GetAttributeValue("incomingemaildeliverymethod"); + } + set + { + OnPropertyChanging("IncomingEmailDeliveryMethod"); + SetAttributeValue("incomingemaildeliverymethod", value); + OnPropertyChanged("IncomingEmailDeliveryMethod"); + } + } + + /// + /// Internal e-mail address for the user. + /// + [AttributeLogicalName("internalemailaddress")] + public string InternalEMailAddress + { + get + { + return GetAttributeValue("internalemailaddress"); + } + set + { + OnPropertyChanging("InternalEMailAddress"); + SetAttributeValue("internalemailaddress", value); + OnPropertyChanged("InternalEMailAddress"); + } + } + + /// + /// User invitation status. + /// + [AttributeLogicalName("invitestatuscode")] + public OptionSetValue InviteStatusCode + { + get + { + return GetAttributeValue("invitestatuscode"); + } + set + { + OnPropertyChanging("InviteStatusCode"); + SetAttributeValue("invitestatuscode", value); + OnPropertyChanged("InviteStatusCode"); + } + } + + /// + /// Information about whether the user is enabled. + /// + [AttributeLogicalName("isdisabled")] + public bool? IsDisabled + { + get + { + return GetAttributeValue("isdisabled"); + } + } + + /// + /// Check if user is an integration user. + /// + [AttributeLogicalName("isintegrationuser")] + public bool? IsIntegrationUser + { + get + { + return GetAttributeValue("isintegrationuser"); + } + set + { + OnPropertyChanging("IsIntegrationUser"); + SetAttributeValue("isintegrationuser", value); + OnPropertyChanged("IsIntegrationUser"); + } + } + + /// + /// Information about whether the user is licensed. + /// + [AttributeLogicalName("islicensed")] + public bool? IsLicensed + { + get + { + return GetAttributeValue("islicensed"); + } + set + { + OnPropertyChanging("IsLicensed"); + SetAttributeValue("islicensed", value); + OnPropertyChanged("IsLicensed"); + } + } + + /// + /// Information about whether the user is synced with the directory. + /// + [AttributeLogicalName("issyncwithdirectory")] + public bool? IsSyncWithDirectory + { + get + { + return GetAttributeValue("issyncwithdirectory"); + } + set + { + OnPropertyChanging("IsSyncWithDirectory"); + SetAttributeValue("issyncwithdirectory", value); + OnPropertyChanged("IsSyncWithDirectory"); + } + } + + /// + /// Job title of the user. + /// + [AttributeLogicalName("jobtitle")] + public string JobTitle + { + get + { + return GetAttributeValue("jobtitle"); + } + set + { + OnPropertyChanging("JobTitle"); + SetAttributeValue("jobtitle", value); + OnPropertyChanged("JobTitle"); + } + } + + /// + /// Last name of the user. + /// + [AttributeLogicalName("lastname")] + public string LastName + { + get + { + return GetAttributeValue("lastname"); + } + set + { + OnPropertyChanging("LastName"); + SetAttributeValue("lastname", value); + OnPropertyChanged("LastName"); + } + } + + /// + /// Middle name of the user. + /// + [AttributeLogicalName("middlename")] + public string MiddleName + { + get + { + return GetAttributeValue("middlename"); + } + set + { + OnPropertyChanging("MiddleName"); + SetAttributeValue("middlename", value); + OnPropertyChanged("MiddleName"); + } + } + + /// + /// Mobile alert e-mail address for the user. + /// + [AttributeLogicalName("mobilealertemail")] + public string MobileAlertEMail + { + get + { + return GetAttributeValue("mobilealertemail"); + } + set + { + OnPropertyChanging("MobileAlertEMail"); + SetAttributeValue("mobilealertemail", value); + OnPropertyChanged("MobileAlertEMail"); + } + } + + /// + /// Mobile phone number for the user. + /// + [AttributeLogicalName("mobilephone")] + public string MobilePhone + { + get + { + return GetAttributeValue("mobilephone"); + } + set + { + OnPropertyChanging("MobilePhone"); + SetAttributeValue("mobilephone", value); + OnPropertyChanged("MobilePhone"); + } + } + + /// + /// Unique identifier of the user who last modified the user. + /// + [AttributeLogicalName("modifiedby")] + public EntityReference ModifiedBy + { + get + { + return GetAttributeValue("modifiedby"); + } + } + + /// + /// Date and time when the user was last modified. + /// + [AttributeLogicalName("modifiedon")] + public DateTime? ModifiedOn + { + get + { + return GetAttributeValue("modifiedon"); + } + } + + /// + /// Unique identifier of the delegate user who last modified the systemuser. + /// + [AttributeLogicalName("modifiedonbehalfby")] + public EntityReference ModifiedOnBehalfBy + { + get + { + return GetAttributeValue("modifiedonbehalfby"); + } + } + + /// + /// Nickname of the user. + /// + [AttributeLogicalName("nickname")] + public string NickName + { + get + { + return GetAttributeValue("nickname"); + } + set + { + OnPropertyChanging("NickName"); + SetAttributeValue("nickname", value); + OnPropertyChanged("NickName"); + } + } + + /// + /// Unique identifier of the organization associated with the user. + /// + [AttributeLogicalName("organizationid")] + public Guid? OrganizationId + { + get + { + return GetAttributeValue("organizationid"); + } + } + + /// + /// Outgoing e-mail delivery method for the user. + /// + [AttributeLogicalName("outgoingemaildeliverymethod")] + public OptionSetValue OutgoingEmailDeliveryMethod + { + get + { + return GetAttributeValue("outgoingemaildeliverymethod"); + } + set + { + OnPropertyChanging("OutgoingEmailDeliveryMethod"); + SetAttributeValue("outgoingemaildeliverymethod", value); + OnPropertyChanged("OutgoingEmailDeliveryMethod"); + } + } + + /// + /// Date and time that the record was migrated. + /// + [AttributeLogicalName("overriddencreatedon")] + public DateTime? OverriddenCreatedOn + { + get + { + return GetAttributeValue("overriddencreatedon"); + } + set + { + OnPropertyChanging("OverriddenCreatedOn"); + SetAttributeValue("overriddencreatedon", value); + OnPropertyChanged("OverriddenCreatedOn"); + } + } + + /// + /// Unique identifier of the manager of the user. + /// + [AttributeLogicalName("parentsystemuserid")] + public EntityReference ParentSystemUserId + { + get + { + return GetAttributeValue("parentsystemuserid"); + } + set + { + OnPropertyChanging("ParentSystemUserId"); + SetAttributeValue("parentsystemuserid", value); + OnPropertyChanged("ParentSystemUserId"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("passporthi")] + public int? PassportHi + { + get + { + return GetAttributeValue("passporthi"); + } + set + { + OnPropertyChanging("PassportHi"); + SetAttributeValue("passporthi", value); + OnPropertyChanged("PassportHi"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("passportlo")] + public int? PassportLo + { + get + { + return GetAttributeValue("passportlo"); + } + set + { + OnPropertyChanging("PassportLo"); + SetAttributeValue("passportlo", value); + OnPropertyChanged("PassportLo"); + } + } + + /// + /// Personal e-mail address of the user. + /// + [AttributeLogicalName("personalemailaddress")] + public string PersonalEMailAddress + { + get + { + return GetAttributeValue("personalemailaddress"); + } + set + { + OnPropertyChanging("PersonalEMailAddress"); + SetAttributeValue("personalemailaddress", value); + OnPropertyChanged("PersonalEMailAddress"); + } + } + + /// + /// URL for the Web site on which a photo of the user is located. + /// + [AttributeLogicalName("photourl")] + public string PhotoUrl + { + get + { + return GetAttributeValue("photourl"); + } + set + { + OnPropertyChanging("PhotoUrl"); + SetAttributeValue("photourl", value); + OnPropertyChanged("PhotoUrl"); + } + } + + /// + /// Preferred address for the user. + /// + [AttributeLogicalName("preferredaddresscode")] + public OptionSetValue PreferredAddressCode + { + get + { + return GetAttributeValue("preferredaddresscode"); + } + set + { + OnPropertyChanging("PreferredAddressCode"); + SetAttributeValue("preferredaddresscode", value); + OnPropertyChanged("PreferredAddressCode"); + } + } + + /// + /// Preferred e-mail address for the user. + /// + [AttributeLogicalName("preferredemailcode")] + public OptionSetValue PreferredEmailCode + { + get + { + return GetAttributeValue("preferredemailcode"); + } + set + { + OnPropertyChanging("PreferredEmailCode"); + SetAttributeValue("preferredemailcode", value); + OnPropertyChanged("PreferredEmailCode"); + } + } + + /// + /// Preferred phone number for the user. + /// + [AttributeLogicalName("preferredphonecode")] + public OptionSetValue PreferredPhoneCode + { + get + { + return GetAttributeValue("preferredphonecode"); + } + set + { + OnPropertyChanging("PreferredPhoneCode"); + SetAttributeValue("preferredphonecode", value); + OnPropertyChanged("PreferredPhoneCode"); + } + } + + /// + /// Unique identifier of the default queue for the user. + /// + [AttributeLogicalName("queueid")] + public EntityReference QueueId + { + get + { + return GetAttributeValue("queueid"); + } + set + { + OnPropertyChanging("QueueId"); + SetAttributeValue("queueid", value); + OnPropertyChanged("QueueId"); + } + } + + /// + /// Salutation for correspondence with the user. + /// + [AttributeLogicalName("salutation")] + public string Salutation + { + get + { + return GetAttributeValue("salutation"); + } + set + { + OnPropertyChanging("Salutation"); + SetAttributeValue("salutation", value); + OnPropertyChanged("Salutation"); + } + } + + /// + /// Check if user is a setup user. + /// + [AttributeLogicalName("setupuser")] + public bool? SetupUser + { + get + { + return GetAttributeValue("setupuser"); + } + set + { + OnPropertyChanging("SetupUser"); + SetAttributeValue("setupuser", value); + OnPropertyChanged("SetupUser"); + } + } + + /// + /// Site at which the user is located. + /// + [AttributeLogicalName("siteid")] + public EntityReference SiteId + { + get + { + return GetAttributeValue("siteid"); + } + set + { + OnPropertyChanging("SiteId"); + SetAttributeValue("siteid", value); + OnPropertyChanged("SiteId"); + } + } + + /// + /// Skill set of the user. + /// + [AttributeLogicalName("skills")] + public string Skills + { + get + { + return GetAttributeValue("skills"); + } + set + { + OnPropertyChanging("Skills"); + SetAttributeValue("skills", value); + OnPropertyChanged("Skills"); + } + } + + /// + /// Unique identifier for the user. + /// + [AttributeLogicalName("systemuserid")] + public Guid? SystemUserId + { + get + { + return GetAttributeValue("systemuserid"); + } + set + { + OnPropertyChanging("SystemUserId"); + SetAttributeValue("systemuserid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = Guid.Empty; + } + OnPropertyChanged("SystemUserId"); + } + } + + [AttributeLogicalName("systemuserid")] + public override Guid Id + { + get + { + return base.Id; + } + set + { + SystemUserId = value; + } + } + + /// + /// Unique identifier of the territory to which the user is assigned. + /// + [AttributeLogicalName("territoryid")] + public EntityReference TerritoryId + { + get + { + return GetAttributeValue("territoryid"); + } + set + { + OnPropertyChanging("TerritoryId"); + SetAttributeValue("territoryid", value); + OnPropertyChanged("TerritoryId"); + } + } + + /// + /// For internal use only. + /// + [AttributeLogicalName("timezoneruleversionnumber")] + public int? TimeZoneRuleVersionNumber + { + get + { + return GetAttributeValue("timezoneruleversionnumber"); + } + set + { + OnPropertyChanging("TimeZoneRuleVersionNumber"); + SetAttributeValue("timezoneruleversionnumber", value); + OnPropertyChanged("TimeZoneRuleVersionNumber"); + } + } + + /// + /// Title of the user. + /// + [AttributeLogicalName("title")] + public string Title + { + get + { + return GetAttributeValue("title"); + } + set + { + OnPropertyChanging("Title"); + SetAttributeValue("title", value); + OnPropertyChanged("Title"); + } + } + + /// + /// Unique identifier of the currency associated with the systemuser. + /// + [AttributeLogicalName("transactioncurrencyid")] + public EntityReference TransactionCurrencyId + { + get + { + return GetAttributeValue("transactioncurrencyid"); + } + set + { + OnPropertyChanging("TransactionCurrencyId"); + SetAttributeValue("transactioncurrencyid", value); + OnPropertyChanged("TransactionCurrencyId"); + } + } + + /// + /// Time zone code that was in use when the record was created. + /// + [AttributeLogicalName("utcconversiontimezonecode")] + public int? UTCConversionTimeZoneCode + { + get + { + return GetAttributeValue("utcconversiontimezonecode"); + } + set + { + OnPropertyChanging("UTCConversionTimeZoneCode"); + SetAttributeValue("utcconversiontimezonecode", value); + OnPropertyChanged("UTCConversionTimeZoneCode"); + } + } + + /// + /// Version number of the user. + /// + [AttributeLogicalName("versionnumber")] + public long? VersionNumber + { + get + { + return GetAttributeValue("versionnumber"); + } + } + + /// + /// Windows Live ID + /// + [AttributeLogicalName("windowsliveid")] + public string WindowsLiveID + { + get + { + return GetAttributeValue("windowsliveid"); + } + set + { + OnPropertyChanging("WindowsLiveID"); + SetAttributeValue("windowsliveid", value); + OnPropertyChanged("WindowsLiveID"); + } + } + + /// + /// Pronunciation of the first name of the user, written in phonetic hiragana or katakana characters. + /// + [AttributeLogicalName("yomifirstname")] + public string YomiFirstName + { + get + { + return GetAttributeValue("yomifirstname"); + } + set + { + OnPropertyChanging("YomiFirstName"); + SetAttributeValue("yomifirstname", value); + OnPropertyChanged("YomiFirstName"); + } + } + + /// + /// Pronunciation of the full name of the user, written in phonetic hiragana or katakana characters. + /// + [AttributeLogicalName("yomifullname")] + public string YomiFullName + { + get + { + return GetAttributeValue("yomifullname"); + } + } + + /// + /// Pronunciation of the last name of the user, written in phonetic hiragana or katakana characters. + /// + [AttributeLogicalName("yomilastname")] + public string YomiLastName + { + get + { + return GetAttributeValue("yomilastname"); + } + set + { + OnPropertyChanging("YomiLastName"); + SetAttributeValue("yomilastname", value); + OnPropertyChanged("YomiLastName"); + } + } + + /// + /// Pronunciation of the middle name of the user, written in phonetic hiragana or katakana characters. + /// + [AttributeLogicalName("yomimiddlename")] + public string YomiMiddleName + { + get + { + return GetAttributeValue("yomimiddlename"); + } + set + { + OnPropertyChanging("YomiMiddleName"); + SetAttributeValue("yomimiddlename", value); + OnPropertyChanged("YomiMiddleName"); + } + } + } +} diff --git a/Ofscrm.PluginRegistration/Entities/Transformation/Magic.cs b/Ofscrm.PluginRegistration/Entities/Transformation/Magic.cs new file mode 100644 index 0000000..7f23463 --- /dev/null +++ b/Ofscrm.PluginRegistration/Entities/Transformation/Magic.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.Xrm.Sdk; + +namespace Ofscrm.PluginRegistration.Entities.Transformation +{ + public static class Magic + { + #region Public Methods + + public static T CastTo(Entity entity) + where T : Entity + { + var instance = (T)Activator.CreateInstance(typeof(T)); + + if (instance != null) + { + instance.Attributes = entity.Attributes; + } + + return instance; + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/AppDomainContext.cs b/Ofscrm.PluginRegistration/Helpers/AppDomainContext.cs new file mode 100644 index 0000000..94f2d19 --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/AppDomainContext.cs @@ -0,0 +1,104 @@ +using System; + +namespace Ofscrm.PluginRegistration.Helpers +{ + public sealed class AppDomainContext : IDisposable + where T : class, new() + { + #region Private Fields + + private bool _disposed; + private AppDomain _domain; + + #endregion Private Fields + + #region Public Constructors + + public AppDomainContext() + : this("TemporaryDomain") + { + } + + public AppDomainContext(string domainName) + { + if (string.IsNullOrWhiteSpace(domainName)) + { + throw new ArgumentNullException("domainName"); + } + + //Create the AppDomain + var setup = new AppDomainSetup(); + setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + + _domain = AppDomain.CreateDomain(domainName, null, setup); + + //Attach the resolver so that assemblies can be resolved correctly + AssemblyResolver.AttachResolver(AppDomain.CurrentDomain); + + //Create the proxy in the AppDomain so that all assemblies that are loaded do not stay loaded in the AppDomain + Proxy = (T)_domain.CreateInstanceFromAndUnwrap(typeof(T).Assembly.Location, typeof(T).FullName); + } + + #endregion Public Constructors + + #region Private Destructors + + ~AppDomainContext() + { + Dispose(false); + } + + #endregion Private Destructors + + #region Public Properties + + public T Proxy + { + get; + private set; + } + + #endregion Public Properties + + #region Public Methods + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion Public Methods + + #region Private Methods + + private void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (null != _domain) + { + try + { + AppDomain.Unload(_domain); + } + catch (CannotUnloadAppDomainException ex) + { + // AppDomain could not be uploaded probably because it was not loaded properly (due to any possible reason) + } + _domain = null; + Proxy = null; + } + + if (disposing) + { + _disposed = true; + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/AssemblyReader.cs b/Ofscrm.PluginRegistration/Helpers/AssemblyReader.cs new file mode 100644 index 0000000..c90e2a9 --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/AssemblyReader.cs @@ -0,0 +1,192 @@ +using System; +using System.Activities; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Wrappers; + +namespace Ofscrm.PluginRegistration.Helpers +{ + public sealed class AssemblyReader : MarshalByRefObject + { + #region Public Constructors + + public AssemblyReader() + { + //Attach the resolver so that assemblies can be resolved correctly + AssemblyResolver.AttachResolver(AppDomain.CurrentDomain); + } + + #endregion Public Constructors + + #region Public Methods + + public CrmPluginAssembly RetrieveAssemblyProperties(string path) + { + if (path == null) + { + throw new ArgumentNullException("path"); + } + else if (!File.Exists(path)) + { + throw new ArgumentException("Path does not point to an existing file"); + } + + return RetrieveAssemblyProperties(LoadAssembly(path), path); + } + + public CrmPluginAssembly RetrievePluginsFromAssembly(string path) + { + if (path == null) + { + throw new ArgumentNullException("path"); + } + else if (!File.Exists(path)) + { + throw new ArgumentException("Path does not point to an existing file"); + } + + //Load the assembly + var assembly = LoadAssembly(path); + var assemblyName = assembly.GetName(); + var defaultGroupName = RegistrationHelper.GenerateDefaultGroupName(assemblyName.Name, assemblyName.Version); + + //Retrieve the assembly properties + var pluginAssembly = RetrieveAssemblyProperties(assembly, path); + + //Loop through each type and process it + var errorList = new List(); + foreach (var t in assembly.GetExportedTypes()) + { + //Plugins and Workflow Activities must be non-abstract classes + if (t.IsAbstract || !t.IsClass) + { + continue; + } + + // Plugins must implement the IPlugin interface + string errorMessage = null; + CrmPluginType type; + CrmPluginIsolatable isolatable; + + //Retrieve the two interface types + var xrmPlugin = t.GetInterface(typeof(IPlugin).FullName); + var v4Plugin = t.GetInterface("Microsoft.Crm.Sdk.IPlugin"); + + var workflowGroupName = defaultGroupName; + var pluginName = t.FullName; + + Version sdkVersion = null; + if (null != xrmPlugin) + { + type = CrmPluginType.Plugin; + isolatable = CrmPluginIsolatable.Yes; + sdkVersion = xrmPlugin.Assembly.GetName().Version; + } + else if (null != v4Plugin) + { + type = CrmPluginType.Plugin; + isolatable = CrmPluginIsolatable.No; + + //It may be that the version of Microsoft.Crm.Sdk.dll will be the v5 version, but it will still be a v4 plug-in. + sdkVersion = new Version(4, 0); + } + else if (t.IsSubclassOf(typeof(CodeActivity)) || t.IsSubclassOf(typeof(Activity))) + { + type = CrmPluginType.WorkflowActivity; + isolatable = CrmPluginIsolatable.Yes; + } + else + { + continue; + } + + //If the SDK version has been set, extract the Major/Minor number + if (null != sdkVersion) + { + pluginAssembly.SdkVersion = new Version(sdkVersion.Major, sdkVersion.Minor); + } + + if (errorMessage != null) + { + errorList.Add(errorMessage); + } + else + { + var plugin = new CrmPlugin(null); + plugin.TypeName = t.FullName; + plugin.Name = pluginName; + plugin.PluginType = type; + plugin.PluginId = Guid.NewGuid(); + plugin.AssemblyId = pluginAssembly.AssemblyId; + plugin.AssemblyName = pluginAssembly.Name; + plugin.Isolatable = isolatable; + + if (type == CrmPluginType.WorkflowActivity && !string.IsNullOrWhiteSpace(workflowGroupName)) + { + plugin.WorkflowActivityGroupName = workflowGroupName; + } + + pluginAssembly.AddPlugin(plugin); + } + } + + return pluginAssembly; + } + + #endregion Public Methods + + #region Private Methods + + private Assembly LoadAssembly(string path) + { + return Assembly.LoadFrom(path); + } + + private CrmPluginAssembly RetrieveAssemblyProperties(Assembly assembly, string path) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + var pluginAssembly = new CrmPluginAssembly(null); + pluginAssembly.AssemblyId = Guid.NewGuid(); + pluginAssembly.SourceType = CrmAssemblySourceType.Disk; + + var fileInfo = new FileInfo(path); + pluginAssembly.ServerFileName = fileInfo.Name; + + var name = assembly.GetName(); + string cultureLabel; + if (name.CultureInfo.LCID == System.Globalization.CultureInfo.InvariantCulture.LCID) + { + cultureLabel = "neutral"; + } + else + { + cultureLabel = name.CultureInfo.Name; + } + + pluginAssembly.Name = name.Name; + pluginAssembly.Version = name.Version.ToString(); + pluginAssembly.Culture = cultureLabel; + + byte[] tokenBytes = name.GetPublicKeyToken(); + if (null == tokenBytes || 0 == tokenBytes.Length) + { + pluginAssembly.PublicKeyToken = null; + } + else + { + pluginAssembly.PublicKeyToken = string.Join(string.Empty, tokenBytes.Select(b => b.ToString("X2"))); + } + + return pluginAssembly; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/AssemblyResolver.cs b/Ofscrm.PluginRegistration/Helpers/AssemblyResolver.cs new file mode 100644 index 0000000..40dccb9 --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/AssemblyResolver.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Ofscrm.PluginRegistration.Helpers +{ + internal static class AssemblyResolver + { + #region Private Fields + + /// + /// Subdirectories that may contain an assembly (if it can't be located). + /// + /// + /// This is useful for architecture specific assemblies that may be different depending on the process architecture + /// of the current assembly. + /// + private static readonly string[] AssemblyProbeSubdirectories = new string[] { string.Empty, "amd64", "i386", @"..\..\..\..\..\private\lib" }; + + /// + /// List of base directories that should be checked + /// + private static Collection _baseDirectories = SetLocations(); + + /// + /// Contains a list of the assemblies that were resolved via the custom assembly resolve event + /// + private static Dictionary _resolvedAssemblies = new Dictionary(); + + #endregion Private Fields + + #region Internal Methods + + /// + /// Attaches the resolver to the current app domain + /// + internal static void AttachResolver() + { + AttachResolver(AppDomain.CurrentDomain); + } + + /// + /// Attaches the resolver to the current app domain + /// + internal static void AttachResolver(AppDomain domain) + { + domain.AssemblyResolve -= new ResolveEventHandler(ResolveAssembly); + + if (null == domain) + { + throw new ArgumentNullException("domain"); + } + + domain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly); + } + + #endregion Internal Methods + + #region Private Methods + + private static Assembly ResolveAssembly(object sender, ResolveEventArgs args) + { + //Check if the assembly has already been resolved + Assembly resolvedAssembly; + if (_resolvedAssemblies.TryGetValue(args.Name, out resolvedAssembly)) + { + return resolvedAssembly; + } + + //Check if the assembly has been already loaded + resolvedAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(x => x.FullName == args.Name).FirstOrDefault(); + + if (resolvedAssembly != null) + { + return resolvedAssembly; + } + + //Create an AssemblyName from the event arguments so that the name can be retrieved + var name = new AssemblyName(args.Name); + + //Create a file name for the assembly to start probing for a location + var fileName = name.Name + ".dll"; + + //Loop through the probing subdirectories to see if the assembly exists + foreach (var baseDirectory in _baseDirectories) + { + foreach (var subdirectory in AssemblyProbeSubdirectories) + { + //Create the file path to the assembly + var assemblyPath = Path.Combine(Path.Combine(baseDirectory, subdirectory), fileName); + + //Check if the file path exists + if (File.Exists(assemblyPath)) + { + //Load the assembly and return it + try + { + var assembly = Assembly.Load(AssemblyName.GetAssemblyName(assemblyPath)); + _resolvedAssemblies[args.Name] = assembly; + return assembly; + } + catch (BadImageFormatException) + { + //Ignore this assembly, because it will not work for the current assembly + } + } + } + } + + _resolvedAssemblies[args.Name] = null; + return null; + } + + private static Collection SetLocations() + { + var list = new Collection(); + var location = string.Empty; + + // Adding current AppDomain location + location = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory).ToUpperInvariant(); + list.Add(location); + + // Searching for plugins in subfolder of current AppDomain location + location = Path.Combine(location, "Plugins").ToUpperInvariant(); + + // Adding (if different) current working folder location + location = Path.GetDirectoryName(Environment.CurrentDirectory).ToUpperInvariant(); + if (!list.Contains(location)) + { + list.Add(location); + } + + // Searching for plugins in subfolder of current working folder location + location = Path.Combine(location, "Plugins").ToUpperInvariant(); + if (!list.Contains(location)) + { + list.Add(location); + } + + return list; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/CrmServiceEndpoint.cs b/Ofscrm.PluginRegistration/Helpers/CrmServiceEndpoint.cs new file mode 100644 index 0000000..abc8e84 --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/CrmServiceEndpoint.cs @@ -0,0 +1,369 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Entities; +using Ofscrm.PluginRegistration.Wrappers; + +namespace Ofscrm.PluginRegistration.Helpers +{ + public enum CrmServiceEndpointConnectionMode + { + Normal = 1, + Federated = 2 + } + + public enum CrmServiceEndpointContract + { + OneWay = 1, + Queue = 2, + Rest = 3, + TwoWay = 4 + } + + public enum CrmServiceEndpointUserClaim + { + None = 1, + UserId = 2, + UserInfo = 3 + } + + public sealed class CrmServiceEndpoint : ICrmEntity + { + #region Public Fields + + public const string ServiceBusPluginAssemblyName = "Microsoft.Crm.ServiceBus"; + public const string ServiceBusPluginName = "Microsoft.Crm.ServiceBus.ServiceBusPlugin"; + public readonly Guid ServiceBusPlugin = new Guid("EF521E63-CD2B-4170-99F6-447466A7161E"); + public readonly Guid ServiceBusPluginAssembly = new Guid("A430B185-D19D-428C-B156-5EBE3F391564"); + + #endregion Public Fields + + #region Private Fields + + private static CrmEntityColumn[] m_entityColumns = null; + private CrmOrganization m_org = null; + + #endregion Private Fields + + #region Public Constructors + + public CrmServiceEndpoint(CrmOrganization org) + { + m_org = org; + } + + public CrmServiceEndpoint(CrmOrganization org, ServiceEndpoint serviceEndpoint) + : this(org) + { + RefreshFromServiceEndpoint(serviceEndpoint); + } + + #endregion Public Constructors + + #region Public Properties + + [XmlIgnore] + [Browsable(false)] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Id", "ServiceEndpointId", typeof(Guid)), + new CrmEntityColumn("Name", "Name", typeof(string)), + new CrmEntityColumn("Description", "Description", typeof(string)), + new CrmEntityColumn("SolutionNamespace", "Solution Namespace", typeof(string)), + new CrmEntityColumn("Path", "Path", typeof(string)), + new CrmEntityColumn("Contract", "Path", typeof(string)), + new CrmEntityColumn("UserClaim", "Path", typeof(string)), + new CrmEntityColumn("ConnectionMode", "Connection Mode", typeof(string)), + new CrmEntityColumn("ModifiedOn", "Modified On", typeof(string)), + new CrmEntityColumn("Isolatable", "Isolatable", typeof(string)), + }; + } + + return m_entityColumns; + } + } + + [Category("Information"), Browsable(false), ReadOnly(true)] + public String AcsIssuerName + { + get; + set; + } + + [Category("Information"), Browsable(false), ReadOnly(true)] + public String AcsManagementKey + { + get; + set; + } + + [Category("Information"), Browsable(false), ReadOnly(true)] + public String AcsPublicCertificate + { + get; + set; + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmServiceEndpointConnectionMode ConnectionMode + { + get; + set; + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmServiceEndpointContract Contract + { + get; + set; + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn { get; private set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Description + { + get; + set; + } + + [Browsable(false)] + public Guid EntityId + { + get { return ServiceEndpointId; } + } + + [Browsable(false)] + public string EntityType + { + get { return ServiceEndpoint.EntityLogicalName; } + } + + [Browsable(false)] + public bool IsSystemCrmEntity + { + get { return false; } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn { get; private set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Name + { + get; + set; + } + + [Browsable(false)] + public CrmPluginStep[] NodeChildren + { + get + { + List steps = new List(); + + foreach (CrmPluginStep step in m_org.Steps.Values) + { + if (step.ServiceBusConfigurationId == ServiceEndpointId) + { + steps.Add(step); + } + } + return steps.ToArray(); + } + } + + [Browsable(false)] + public Guid NodeId + { + get { return ServiceEndpointId; } + } + + [Browsable(false)] + public string NodeText + { + get + { + return string.Format("({0}) {1}", NodeTypeLabel, string.IsNullOrWhiteSpace(Name) ? Description : Name); + } + } + + [Browsable(false)] + public string NodeTypeLabel + { + get { return "ServiceEndpoint"; } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Path + { + get; + set; + } + + [Browsable(false)] + public Guid PluginId + { + get { return ServiceBusPlugin; } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid ServiceEndpointId + { + get; + set; + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string SolutionNamespace + { + get; + set; + } + + [Browsable(false)] + public CrmEntityDictionary Steps + { + get + { + Dictionary steps = new Dictionary(); + + foreach (CrmPluginStep step in m_org.Steps.Values) + { + if (step.ServiceBusConfigurationId == ServiceEndpointId) + { + steps.Add(step.StepId, step); + } + } + return new CrmEntityDictionary(steps); + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmServiceEndpointUserClaim UserClaim + { + get; + set; + } + + [XmlIgnore] + [Browsable(false)] + public Dictionary Values + { + get + { + Dictionary valueList = new Dictionary(); + valueList.Add("Id", ServiceEndpointId.ToString()); + valueList.Add("Name", Name); + valueList.Add("Description", Description); + valueList.Add("SolutionNamespace", SolutionNamespace); + valueList.Add("Path", Path); + valueList.Add("Contract", Contract.ToString()); + valueList.Add("UserClaim", UserClaim.ToString()); + valueList.Add("ConnectionMode", ConnectionMode.ToString()); + valueList.Add("ModifiedOn", ModifiedOn); + valueList.Add("CreatedOn", CreatedOn); + return valueList; + } + } + + #endregion Public Properties + + #region Public Methods + + public Dictionary GenerateCrmEntities() + { + Dictionary entityList = new Dictionary(); + + ServiceEndpoint serviceEndPoint = new ServiceEndpoint(); + if (ServiceEndpointId != Guid.Empty) + { + serviceEndPoint.Id = ServiceEndpointId; + } + + serviceEndPoint.ConnectionMode = new OptionSetValue(); + serviceEndPoint.ConnectionMode.Value = (int)ConnectionMode; + + serviceEndPoint.Contract = new OptionSetValue(); + serviceEndPoint.Contract.Value = (int)Contract; + + serviceEndPoint.UserClaim = new OptionSetValue((int)UserClaim); + + serviceEndPoint.Description = Description; + serviceEndPoint.Name = Name; + serviceEndPoint.Path = Path; + serviceEndPoint.SolutionNamespace = SolutionNamespace; + + entityList.Add(ServiceEndpoint.EntityLogicalName, serviceEndPoint); + + return entityList; + } + + public void RefreshFromServiceEndpoint(ServiceEndpoint serviceEndPoint) + { + if (serviceEndPoint == null) + { + throw new ArgumentNullException("serviceEndPoint"); + } + + Name = serviceEndPoint.Name; + Description = serviceEndPoint.Description; + Path = serviceEndPoint.Path; + SolutionNamespace = serviceEndPoint.SolutionNamespace; + + if (serviceEndPoint.ServiceEndpointId != Guid.Empty) + { + ServiceEndpointId = serviceEndPoint.ServiceEndpointId.Value; + } + + if (serviceEndPoint.CreatedOn != null && (serviceEndPoint.CreatedOn.HasValue)) + { + CreatedOn = serviceEndPoint.CreatedOn.Value; + } + + if (serviceEndPoint.ModifiedOn != null && (serviceEndPoint.ModifiedOn.HasValue)) + { + ModifiedOn = serviceEndPoint.ModifiedOn.Value; + } + + if (serviceEndPoint.ConnectionMode != null) + { + ConnectionMode = (CrmServiceEndpointConnectionMode)Enum.ToObject(typeof(CrmServiceEndpointConnectionMode), serviceEndPoint.ConnectionMode.Value); + } + + if (serviceEndPoint.Contract != null) + { + Contract = (CrmServiceEndpointContract)Enum.ToObject(typeof(CrmServiceEndpointContract), + serviceEndPoint.Contract.Value); + } + if (serviceEndPoint.UserClaim != null) + { + UserClaim = (CrmServiceEndpointUserClaim)Enum.ToObject(typeof(CrmServiceEndpointUserClaim), + serviceEndPoint.UserClaim.Value); + } + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + CreatedOn = createdOn; + } + + if (modifiedOn != null) + { + ModifiedOn = modifiedOn; + } + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/OrganizationConnectionOptions.cs b/Ofscrm.PluginRegistration/Helpers/OrganizationConnectionOptions.cs new file mode 100644 index 0000000..c860dee --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/OrganizationConnectionOptions.cs @@ -0,0 +1,12 @@ +namespace Ofscrm.PluginRegistration.Helpers +{ + public class OrganizationConnectionOptions + { + public bool LoadPlugins { get; set; } + public bool LoadMessageEntities { get; set; } + public bool LoadAssemblies { get; set; } + public bool LoadServiceEndpoints { get; set; } + public bool LoadSteps { get; set; } + public bool LoadImages { get; set; } + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/OrganizationHelper.cs b/Ofscrm.PluginRegistration/Helpers/OrganizationHelper.cs new file mode 100644 index 0000000..d771a5e --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/OrganizationHelper.cs @@ -0,0 +1,1210 @@ +// ===================================================================== +// +// This file is part of the Microsoft Dynamics CRM SDK code samples. +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// ===================================================================== + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.ServiceModel; +using Microsoft.Crm.Sdk.Messages; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Client; +using Microsoft.Xrm.Sdk.Messages; +using Microsoft.Xrm.Sdk.Metadata; +using Microsoft.Xrm.Sdk.Query; +using Ofscrm.PluginRegistration.Entities; +using Ofscrm.PluginRegistration.Entities.Transformation; +using Ofscrm.PluginRegistration.Wrappers; + +namespace Ofscrm.PluginRegistration.Helpers +{ + public static class OrganizationHelper + { + internal const string V3CalloutProxyTypeName = "Microsoft.Crm.Extensibility.V3CalloutProxyPlugin"; + + private static Dictionary m_entityColumns = new Dictionary(); + private volatile static List m_messageList = new List(); + + public static void RefreshConnection(CrmOrganization org, CrmEntityDictionary messages, OrganizationConnectionOptions connectionOptions) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + org.Connected = false; + + OpenConnection(org, messages, connectionOptions); + } + + ///// + ///// Retrieve the Message entities for the organization. This will be the same for each deployment and organization. + ///// + ///// Organization to be used + //public static List LoadMessages(CrmOrganization org) + //{ + // return LoadMessages(org, null); + //} + + public static CrmEntityDictionary RetrieveMessages(CrmOrganization org) + { + lock (m_messageList) + { + if (m_messageList.Count == 0) + { + m_messageList = OrganizationHelper.LoadMessages(org); + } + + Dictionary messageList = new Dictionary(); + foreach (CrmMessage msg in m_messageList) + { + CrmMessage newMessage = new CrmMessage(null, msg.MessageId, msg.Name, + msg.SupportsFilteredAttributes, msg.CustomizationLevel, msg.CreatedOn, msg.ModifiedOn, + msg.ImageMessagePropertyNames); + + messageList.Add(newMessage.MessageId, newMessage); + } + + return new CrmEntityDictionary(messageList); + } + } + + /// + /// Retrieve the Message entities for the organization. This will be the same for each deployment and organization. + /// + /// Organization to be used + /// ProgressIndicator that will show the progress as the object is loaded + public static List LoadMessages(CrmOrganization org) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + //Generate the query + var query = new QueryExpression(); + query.ColumnSet = GetColumnSet(SdkMessage.EntityLogicalName); + query.Criteria.AddCondition("isprivate", ConditionOperator.Equal, false); + query.AddOrder("name", OrderType.Ascending); + query.EntityName = SdkMessage.EntityLogicalName; + + //Retrieve the message entities + var results = org.OrganizationService.RetrieveMultipleAllPages(query); + + //Process each message entity + var msgList = new List(); + for (int i = 0; i < results.Entities.Count; i++) + { + msgList.Add(UpdateMessageProperties(new CrmMessage(null, Magic.CastTo(results[i])))); + } + + return msgList; + } + + /// + /// Initializes any items that need to be initialized when the connection gets opened + /// + /// Organization that should be opened + /// List of messages + /// + public static void OpenConnection(CrmOrganization org, CrmEntityDictionary messages, + OrganizationConnectionOptions connectionOptions) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (org.Connected) + { + return; + } + + bool loadedCompletely = false; + try + { + //Initialize the services + org.Initialize(); + + //Initialize list of users + LoadUsers(org); + + //Find the current user + org.LoggedOnUser = GetLoggedOnUser(org); + + //Initialize list of messages + LoadMessageEntities(org, messages); + + //Initialize list of assemblies + LoadAssemblies(org); + + //Initialize list of plugins + Dictionary typeList; + LoadPlugins(org, out typeList); + + //Initialize list of service end points + LoadServiceEndpoints(org); + + //Initialize list of steps + Dictionary stepList; + LoadSteps(org, typeList, out stepList); + + //Initialize list of images + LoadImages(org, stepList); + + org.ClearAllEntityAttributes(); + + loadedCompletely = true; + } + finally + { + org.Connected = loadedCompletely; + } + } + + /// + /// Loads/Reloads assemblies from CRM + /// + /// Assembly Ids to reload (does not reload plugins). If not specified, reloads all assemblies + public static void LoadAssemblies(CrmOrganization org) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + var query = new QueryExpression(); + query.ColumnSet = GetColumnSet(PluginAssembly.EntityLogicalName); + query.Criteria = CreateAssemblyFilter(); + query.EntityName = PluginAssembly.EntityLogicalName; + + //Clear the assemblies list since we are reloading from scratch + org.ClearAssemblies(); + + foreach (var assembly in org.OrganizationService.RetrieveMultipleAllPages(query).Entities.Select(x => Magic.CastTo(x))) + { + org.AddAssembly(new CrmPluginAssembly(org, assembly)); + } + } + + /// + /// Loads/Reloads Service Endpoitns from CRM + /// + public static void LoadServiceEndpoints(CrmOrganization org) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + QueryExpression query = new QueryExpression(); + query.ColumnSet = GetColumnSet(ServiceEndpoint.EntityLogicalName); + query.Criteria = new FilterExpression(); + query.EntityName = ServiceEndpoint.EntityLogicalName; + + //Clear the Service Endpoints list since we are reloading from scratch + org.ClearServiceEndpoints(); + + foreach (var serviceEndPoint in org.OrganizationService.RetrieveMultipleAllPages(query).Entities.Select(x => Magic.CastTo(x))) + { + org.AddServiceEndpoint(new CrmServiceEndpoint(org, serviceEndPoint)); + } + } + + /// + /// Retrieves a list of attributes for a specified attribute in a DataTable + /// + /// Name of the entity + /// ProgressIndicator that will show the progress as the object is loaded + /// DataTable containing the attributes + public static void LoadAttributeList(CrmOrganization org, string entityName) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (entityName == null) + { + throw new ArgumentNullException("entityName"); + } + + RetrieveEntityRequest request = new RetrieveEntityRequest(); + request.EntityFilters = EntityFilters.Attributes; + request.LogicalName = entityName; + request.RetrieveAsIfPublished = false; + + //Execute the request + RetrieveEntityResponse response = (RetrieveEntityResponse)org.OrganizationService.Execute(request); + + EntityMetadata entityMd = response.EntityMetadata; + + List attList = new List(); + + foreach (AttributeMetadata att in entityMd.Attributes) + { + // Do not add the child attributes + // Do not add the attributes that are not valid for Read + if (att.IsValidForRead.Value && null == att.AttributeOf) + { + attList.Add(new CrmAttribute(att, att.LogicalName == entityMd.PrimaryIdAttribute)); + } + } + + org.SaveEntityAttributes(entityName, attList.ToArray()); + } + + /// + /// Creates a DataTable from the given Dictionary of CrmEntity objects + /// + public static DataTable CreateDataTable(CrmEntityColumn[] columns, IEnumerable enumerable) + where Entity : ICrmEntity + { + if (columns == null) + { + throw new ArgumentNullException("columns"); + } + else if (enumerable == null) + { + throw new ArgumentNullException("enumerable"); + } + + //Create the data table + DataTable table = new DataTable(typeof(Entity).Name); + + //Create the list of columns + foreach (CrmEntityColumn col in columns) + { + DataColumn tableCol = table.Columns.Add(col.Name, col.Type); + if (col.Label != null) + { + tableCol.Caption = col.Label; + } + } + + //Create the list of rows + foreach (Entity entity in enumerable) + { + DataRow row = table.NewRow(); + + foreach (KeyValuePair value in entity.Values) + { + row[value.Key] = value.Value; + } + + table.Rows.Add(row); + } + + return table; + } + + /// + /// Updates the dates of the entities + /// + /// Organization that contains the entities + /// List of entities to be updated + public static void UpdateDates(CrmOrganization org, List entityList) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (entityList == null) + { + throw new ArgumentNullException("entityList"); + } + + Dictionary updateList = new Dictionary(); + Dictionary> queryList = new Dictionary>(); + foreach (ICrmEntity entity in entityList) + { + if (entity != null) + { + if (queryList.ContainsKey(entity.EntityType)) + { + queryList[entity.EntityType].Add(entity.EntityId); + } + else + { + List idList = new List(); + idList.Add(entity.EntityId); + + queryList.Add(entity.EntityType, idList); + } + + updateList.Add(entity.EntityId, entity); + } + } + + if (queryList.Count == 0) + { + return; + } + + //Create the base query that will be used + + string[] colsArray = new string[] { "modifiedon", "createdon" }; + var idCon = new ConditionExpression(); + idCon.AttributeName = string.Empty; + idCon.Operator = ConditionOperator.In; + + var query = new QueryExpression(); + query.Criteria.Conditions.Add(idCon); + + foreach (KeyValuePair> entityIdList in queryList) + { + query.EntityName = entityIdList.Key.ToString(); + + idCon.AttributeName = query.EntityName + "id"; + idCon.Values.Clear(); + idCon.Values.AddRange(ConvertToObjectArray(entityIdList.Value)); + query.ColumnSet = new ColumnSet(colsArray); + + foreach (Entity entity in org.OrganizationService.RetrieveMultipleAllPages(query).Entities) + { + DateTime? created = null; + DateTime? modified = null; + Guid id = Guid.Empty; + + foreach (var prop in entity.Attributes) + { + DateTime? dateValue = prop.Value as DateTime?; + if (null != dateValue) + { + switch (prop.Key) + { + case "createdon": + created = dateValue.Value; + break; + + case "modifiedon": + modified = dateValue.Value; + break; + } + } + else + { + Guid? idValue = prop.Value as Guid?; + if (null != idValue) + { + id = (Guid)idValue; + } + } + } + + if (id != Guid.Empty) + { + updateList[id].UpdateDates(created, modified); + } + } + } + } + + public static void RefreshAssembly(CrmOrganization org, CrmPluginAssembly assembly) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + var assemblyRetrievedFromDatabase = Magic.CastTo(org.OrganizationService.Retrieve(PluginAssembly.EntityLogicalName, assembly.AssemblyId, GetColumnSet(PluginAssembly.EntityLogicalName))); + assembly.RefreshFromPluginAssembly(assemblyRetrievedFromDatabase); + } + + public static void RefreshPlugin(CrmOrganization org, CrmPlugin plugin) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + + var pluginRetrievedFromDatabase = Magic.CastTo(org.OrganizationService.Retrieve(PluginType.EntityLogicalName, plugin.PluginId, GetColumnSet(PluginType.EntityLogicalName))); + plugin.RefreshFromPluginType(pluginRetrievedFromDatabase); + } + + public static void RefreshStep(CrmOrganization org, CrmPluginStep step) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + if (step == null) + { + throw new ArgumentNullException("step"); + } + + var stepRetrievedFromDatabase = Magic.CastTo(org.OrganizationService.Retrieve(Entities.SdkMessageProcessingStep.EntityLogicalName, step.StepId, GetColumnSet(Entities.SdkMessageProcessingStep.EntityLogicalName))); + step.RefreshFromSdkMessageProcessingStep(step.AssemblyId, stepRetrievedFromDatabase, step.SecureConfiguration); + } + + public static void RefreshImage(CrmOrganization org, CrmPluginImage image, CrmPluginStep step) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (step == null) + { + throw new ArgumentNullException("step"); + } + else if (image == null) + { + throw new ArgumentNullException("image"); + } + + var imageRetrievedFromDatabase = Magic.CastTo(org.OrganizationService.Retrieve(SdkMessageProcessingStepImage.EntityLogicalName, image.ImageId, GetColumnSet(SdkMessageProcessingStepImage.EntityLogicalName))); + if (step.IsProfiled && null != imageRetrievedFromDatabase.SdkMessageProcessingStepId) + { + imageRetrievedFromDatabase.SdkMessageProcessingStepId.Id = step.StepId; + } + + image.RefreshFromSdkMessageProcessingStepImage(step.AssemblyId, step.PluginId, imageRetrievedFromDatabase); + } + + public static void RefreshServiceEndpoint(CrmOrganization org, CrmServiceEndpoint sep) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + if (sep == null) + { + throw new ArgumentNullException("sep"); + } + + var sepRetrievedFromDatabase = Magic.CastTo(org.OrganizationService.Retrieve(ServiceEndpoint.EntityLogicalName, sep.ServiceEndpointId, GetColumnSet(ServiceEndpoint.EntityLogicalName))); + sep.RefreshFromServiceEndpoint(sepRetrievedFromDatabase); + } + + public static string ExecutingDirectory + { + get + { + return new System.IO.FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName; + } + } + + /// + /// Indicates that the step can be exported + /// + /// Step to be checked + /// True if step can be exported + public static bool AllowStepImportExport(CrmPluginStep step) + { + if (step == null) + { + throw new ArgumentNullException("step"); + } + + if (step.CustomizationLevel == 0) + { + switch (step.Organization.Plugins[step.PluginId].TypeName) + { + case "Microsoft.Crm.ServiceBus.ServiceBusPlugin": + return true; + + default: + return false; + } + } + else + { + return true; + } + } + + /// + /// Indicates that the plugin allows registration of steps + /// + /// Plugin to be checked + /// True if steps can be registered on the plugin + public static bool AllowStepRegistrationForPlugin(CrmPlugin plugin) + { + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + + if (plugin.CustomizationLevel == 0) + { + switch (plugin.TypeName) + { + case "Microsoft.Crm.ServiceBus.ServiceBusPlugin": + return true; + + default: + return false; + } + } + else + { + return true; + } + } + + #region Private Helper Methods + + private static CrmMessage UpdateMessageProperties(CrmMessage message) + { + switch (message.Name) + { + case "Assign": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Target, "Assigned Entity")); + break; + + case "Create": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Id, "Created Entity")); + break; + + case "Delete": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Target, "Deleted Entity")); + break; + + case "DeliverIncoming": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.EmailId, "Delivered E-mail Id")); + break; + + case "DeliverPromote": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.EmailId, "Delivered E-mail Id")); + break; + + case "ExecuteWorkflow": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Target, "Workflow Entity", null)); + break; + + case "Merge": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Target, + "Parent Entity", "Entity into which the data from the Child Entity is being merged.")); + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.SubordinateId, + "Child Entity", "Entity that is being merged into the Parent Entity.")); + break; + + case "Route": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Target, "Routed Entity", null)); + break; + + case "Send": + //This is only applicable for Send message when the entity is e-mail. If the entity is template + //or fax, then the parameter should be ParameterName.FaxId or ParameterName.TemplateId + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.EmailId, "Sent Entity Id")); + break; + + case "SetState": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.EntityMoniker, "Entity")); + break; + + case "SetStateDynamicEntity": + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.EntityMoniker, "Entity")); + break; + + case "Update": + message.SupportsFilteredAttributes = true; + message.ImageMessagePropertyNames.Add( + new ImageMessagePropertyName(ParameterName.Target, "Updated Entity")); + break; + + default: + //There are no valid message property names for images for any other messages + break; + } + + return message; + } + + private static void LoadUsers(CrmOrganization org) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + //Retrieve all of the users + var users = new OrganizationServiceContext(org.OrganizationService) + // Creating query for given entity, with no conditions + .CreateQuery(SystemUser.EntityLogicalName) + // Executing LINQ-to-SQL query, not optimal, but safe for early-bound + .ToArray() + .Select(x => Magic.CastTo(x)) + .Select(x => + { + return new CrmUser(org) + { + UserId = x.SystemUserId.GetValueOrDefault(), + Name = x.FullName, + DomainName = x.DomainName, + InternalEmailAddress = x.InternalEMailAddress, + Enabled = !x.IsDisabled.GetValueOrDefault() + }; + }) + // Final sorting of results + .OrderBy(x => x.Name); + + //Loop through the users that were returned from the server + org.Users.Clear(); + foreach (var user in users) + { + //Create the CrmUser object + org.Users.Add(user.UserId, user); + } + } + + private static void LoadMessageEntities(CrmOrganization org, CrmEntityDictionary messages) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (messages == null) + { + throw new ArgumentNullException("messages"); + } + else if (messages.Count == 0) + { + return; + } + + org.ClearMessages(); + + //Load the list of filters + List messageIdList = new List(); + foreach (CrmMessage message in messages) + { + messageIdList.Add(message.MessageId); + } + + var query = new QueryExpression(); + query.ColumnSet = GetColumnSet(SdkMessageFilter.EntityLogicalName); + query.Criteria.AddCondition("sdkmessageid", ConditionOperator.In, messageIdList.ToArray()); + query.Criteria.AddCondition("iscustomprocessingstepallowed", ConditionOperator.Equal, true); + query.Criteria.AddCondition("isvisible", ConditionOperator.Equal, true); + query.Criteria.FilterOperator = LogicalOperator.And; + query.EntityName = SdkMessageFilter.EntityLogicalName; + + foreach (var filter in org.OrganizationService.RetrieveMultipleAllPages(query).Entities.Select(x => Magic.CastTo(x))) + { + var entity = new CrmMessageEntity(org, filter); + var message = messages[entity.MessageId]; + if (message.Organization == null) + { + message.Organization = org; + org.AddMessage(message); + } + + message.AddMessageEntity(entity); + } + } + + private static void LoadPlugins(CrmOrganization org, out Dictionary typeList) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + //Create the query + var query = new QueryExpression(PluginType.EntityLogicalName); + query.ColumnSet = GetColumnSet(PluginType.EntityLogicalName); + query.Criteria = new FilterExpression(); + query.Criteria.AddCondition("typename", ConditionOperator.NotLike, "Compiled.Workflow%"); + + //Add a filter to only include the desired system plugins + var systemAssemblyFilter = query.Criteria.AddFilter(LogicalOperator.Or); + systemAssemblyFilter.AddCondition("customizationlevel", ConditionOperator.Null); + systemAssemblyFilter.AddCondition("customizationlevel", ConditionOperator.NotEqual, 0); + systemAssemblyFilter.AddCondition("typename", ConditionOperator.In, + "Microsoft.Crm.Extensibility.InternalOperationPlugin", + V3CalloutProxyTypeName, + "Microsoft.Crm.ServiceBus.ServiceBusPlugin"); + + //Link to the assembly to ensure that only valid plug-ins are retrieved + var assemblyLink = query.AddLink(PluginAssembly.EntityLogicalName, "pluginassemblyid", "pluginassemblyid"); + assemblyLink.LinkCriteria = CreateAssemblyFilter(); + + //Retrieve the results + var results = org.OrganizationService.RetrieveMultipleAllPages(query); + + //Initialize the map + bool profilerPluginLocated = false;//!OrganizationHelper.IsProfilerSupported; + typeList = new Dictionary(); + + foreach (var plugin in results.Entities.Select(x => Magic.CastTo(x))) + { + var assembly = org.Assemblies[plugin.PluginAssemblyId.Id]; + if (assembly.Plugins.ContainsKey(plugin.PluginTypeId.Value)) + { + assembly[plugin.PluginTypeId.Value].RefreshFromPluginType(plugin); + } + else + { + assembly.AddPlugin(new CrmPlugin(org, plugin)); + } + + var crmPlugin = assembly[plugin.PluginTypeId.Value]; + if (!profilerPluginLocated) + { + bool isProfilerPlugin = false;// IsProfilerPlugin(crmPlugin); + crmPlugin.IsProfilerPlugin = isProfilerPlugin; + profilerPluginLocated = isProfilerPlugin; + + if (isProfilerPlugin) + { + org.ProfilerPlugin = crmPlugin; + assembly.IsProfilerAssembly = true; + } + } + + typeList.Add(plugin.PluginTypeId.Value, crmPlugin); + } + } + + private static void LoadSteps(CrmOrganization org, Dictionary typeList, out Dictionary crmStepList) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + const string SecureConfigurationAttributeName = "config.secureconfig"; + + var stepList = new List(); + var secureConfigIdList = new List(); + + //Create the query for the step + var query = new QueryExpression(SdkMessageProcessingStep.EntityLogicalName); + query.ColumnSet = GetColumnSet(SdkMessageProcessingStep.EntityLogicalName); + query.Criteria = CreateStepFilter(); + + //Only add this link if retrieval of the secure configuration has not failed previously + LinkEntity secureConfigurationLink; + if (org.SecureConfigurationPermissionDenied) + { + secureConfigurationLink = null; + } + else + { + //Create the link for the secure configuration + secureConfigurationLink = query.AddLink(SdkMessageProcessingStepSecureConfig.EntityLogicalName, + "sdkmessageprocessingstepsecureconfigid", "sdkmessageprocessingstepsecureconfigid", JoinOperator.LeftOuter); + secureConfigurationLink.EntityAlias = "config"; + secureConfigurationLink.Columns = GetColumnSet(SdkMessageProcessingStepSecureConfig.EntityLogicalName); + } + + //Execute the query + EntityCollection results; + try + { + results = org.OrganizationService.RetrieveMultipleAllPages(query); + } + catch (FaultException ex) + { + //Privilege Denied Error Code + if (null != secureConfigurationLink && 0x80040220 == (uint)ex.Detail.ErrorCode) + { + //Set the flag + org.SecureConfigurationPermissionDenied = true; + + //Remove the secure configuration link + query.LinkEntities.Remove(secureConfigurationLink); + + //Execute the request without the link + results = org.OrganizationService.RetrieveMultipleAllPages(query); + } + else + { + throw; + } + } + + //Loop through the results and process them + var profiledStepList = new Dictionary(); + crmStepList = new Dictionary(); + foreach (var step in results.Entities.Select(x => Magic.CastTo(x))) + { + var secureConfig = step.GetAttributeValue(SecureConfigurationAttributeName); + + //Check if the secure configuration was retrieved + bool invalidSecureConfigurationId = false; + if (null != step.SdkMessageProcessingStepSecureConfigId && null == secureConfig && + !org.SecureConfigurationPermissionDenied) + { + invalidSecureConfigurationId = true; + } + + //Retrieve the secure configuration + string secureConfiguration = (null == secureConfig ? null : (string)secureConfig.Value); + + //Retrieve the plug-in +#pragma warning disable 0612 + Guid pluginId = (step.PluginTypeId != null) ? step.PluginTypeId.Id : Guid.Empty; +#pragma warning restore 0612 + + CrmPlugin plugin; + if (null != typeList && typeList.TryGetValue(pluginId, out plugin)) + { + CrmPluginStep crmStep; + if (plugin.Steps.TryGetValue(step.SdkMessageProcessingStepId.GetValueOrDefault(), out crmStep)) + { + crmStep.RefreshFromSdkMessageProcessingStep(plugin.AssemblyId, step, secureConfiguration); + } + else + { + crmStep = new CrmPluginStep(org, plugin.AssemblyId, step, secureConfiguration); + plugin.AddStep(crmStep); + } + + if (plugin.IsProfilerPlugin) + { + // ProfilerConfiguration configuration = RetrieveProfilerConfiguration(crmStep); + //if (null != configuration) + //{ + // EntityReference profiledHandler = configuration.EventHandler; + // if (configuration.IsContextReplay.GetValueOrDefault()) + // { + // crmStep.ProfilerStepId = crmStep.StepId; + // } + // else if (null != profiledHandler && !profiledStepList.ContainsKey(profiledHandler.Id)) + // { + // profiledStepList[profiledHandler.Id] = crmStep; + // crmStep.ProfilerOriginalStepId = profiledHandler.Id; + // } + //} + } + + crmStep.SecureConfigurationRecordIdInvalid = invalidSecureConfigurationId; + + crmStepList.Add(step.SdkMessageProcessingStepId.Value, plugin.Steps[step.SdkMessageProcessingStepId.Value]); + } + } + + //Looping through each step that is being profiled and mark it with the corresponding "Profiler Step" (plug-in instance of + //the Plug-in Profiler that takes the place of the original plug-in) so that it can be rendered correctly in the UI + foreach (KeyValuePair pair in profiledStepList) + { + CrmPluginStep step; + if (crmStepList.TryGetValue(pair.Key, out step)) + { + step.ProfilerStepId = pair.Value.StepId; + + //If the step is profiled, the actual profiled step should not be listed in any of the trees, etc. + CrmPluginStep profiledStep = pair.Value; + profiledStep.Organization.Plugins[profiledStep.PluginId].RemoveStep(profiledStep.StepId); + } + } + } + + /// + /// Loads the images + /// + /// + /// + /// List of steps that were registered + /// + private static void LoadImages(CrmOrganization org, Dictionary stepList) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + var query = new QueryExpression(SdkMessageProcessingStepImage.EntityLogicalName); + query.ColumnSet = GetColumnSet(SdkMessageProcessingStepImage.EntityLogicalName); + + //Put this extra exclusion because any published Workflows will create + //Images (linked to the Step for Workflow Expansion). Since we are using InnerJoin, + //any images that reference invalid steps will be excluded. This is okay, because + //images without steps will have no effect in the system. + var parentLink = query.AddLink(SdkMessageProcessingStep.EntityLogicalName, "sdkmessageprocessingstepid", "sdkmessageprocessingstepid"); + parentLink.LinkCriteria = CreateStepFilter(); + + //Execute the query + foreach (var image in org.OrganizationService.RetrieveMultipleAllPages(query).Entities.Select(x => Magic.CastTo(x))) + { + CrmPluginStep step; + if (null != stepList && stepList.TryGetValue(image.SdkMessageProcessingStepId.Id, out step)) + { + //If this is a profiled step, the image should be parented by the original step + if (null != step.ProfilerOriginalStepId) + { + if (!stepList.TryGetValue(step.ProfilerOriginalStepId.GetValueOrDefault(), out step)) + { + continue; + } + + image.SdkMessageProcessingStepId.Id = step.StepId; + } + + CrmPluginImage existingImage; + if (step.Images.TryGetValue(image.Id, out existingImage)) + { + existingImage.RefreshFromSdkMessageProcessingStepImage(step.AssemblyId, step.StepId, image); + } + else + { + step.AddImage(new CrmPluginImage(org, step.AssemblyId, step.PluginId, image)); + } + } + } + } + + private static FilterExpression CreateAssemblyFilter() + { + var criteria = new FilterExpression(); + + //Exclude all compiled workflow assemblies that may remain after upgrade + criteria.AddCondition("name", ConditionOperator.NotLike, "CompiledWorkflow%"); + + //Exclude any system assemblies that shouldn't be included + var systemAssemblyFilter = criteria.AddFilter(LogicalOperator.Or); + systemAssemblyFilter.AddCondition("customizationlevel", ConditionOperator.Null); + systemAssemblyFilter.AddCondition("customizationlevel", ConditionOperator.NotEqual, 0); + systemAssemblyFilter.AddCondition("name", ConditionOperator.In, "Microsoft.Crm.ObjectModel", "Microsoft.Crm.ServiceBus"); + + return criteria; + } + + private static FilterExpression CreateStepFilter() + { + var criteria = new FilterExpression(); + + //Exclude all steps that are not in the supported stages + criteria.AddCondition("stage", ConditionOperator.In, "10", "20", "40", "50"); + + return criteria; + } + + /// + /// Retrieves the needed columns for the specified entity + /// + /// Entity for which to generate the columns + private static ColumnSet GetColumnSet(string entityName) + { + if (!m_entityColumns.ContainsKey(entityName)) + { + ColumnSet cols = new ColumnSet(); + switch (entityName) + { + case ServiceEndpoint.EntityLogicalName: + cols.AddColumns( + "name", + "createdon", + "modifiedon", + "serviceendpointid", + "path", + "contract", + "userclaim", + "solutionnamespace", + "connectionmode", + "description"); + break; + + case PluginAssembly.EntityLogicalName: + cols.AddColumns( + "name", + "createdon", + "modifiedon", + "customizationlevel", + "pluginassemblyid", + "sourcetype", + "path", + "version", + "publickeytoken", + "culture", + "isolationmode", + "description"); + break; + + case PluginType.EntityLogicalName: + cols.AddColumns( + "plugintypeid", + "friendlyname", + "createdon", + "modifiedon", + "customizationlevel", + "assemblyname", + "typename", + "pluginassemblyid", + "isworkflowactivity", + "name", + "description", + "workflowactivitygroupname"); + break; + + case SdkMessage.EntityLogicalName: + cols.AddColumns( + "sdkmessageid", + "createdon", + "modifiedon", + "name", + "customizationlevel"); + break; + + case SdkMessageFilter.EntityLogicalName: + cols.AddColumns( + "sdkmessagefilterid", + "createdon", + "modifiedon", + "sdkmessageid", + "primaryobjecttypecode", + "secondaryobjecttypecode", + "customizationlevel", + "availability"); + break; + + case SdkMessageProcessingStep.EntityLogicalName: + cols.AddColumns( + "name", + "mode", + "customizationlevel", + "stage", + "rank", + "sdkmessageid", + "sdkmessagefilterid", + "plugintypeid", + "supporteddeployment", + "description", + "asyncautodelete", + "impersonatinguserid", + "configuration", + "sdkmessageprocessingstepsecureconfigid", + "statecode", + "invocationsource", + "modifiedon", + "createdon", + "filteringattributes", + "eventhandler"); + break; + + case SdkMessageProcessingStepImage.EntityLogicalName: + cols.AddColumns( + "name", + "attributes", + "customizationlevel", + "entityalias", + "createdon", + "modifiedon", + "imagetype", + "sdkmessageprocessingstepid", + "messagepropertyname", + "relatedattributename"); + break; + + case SdkMessageProcessingStepSecureConfig.EntityLogicalName: + cols.AddColumns( + "sdkmessageprocessingstepsecureconfigid", + "secureconfig"); + break; + + default: + throw new NotImplementedException(entityName.ToString()); + } + + m_entityColumns.Add(entityName, cols); + } + + return m_entityColumns[entityName]; + } + + /// + /// Returns the Id field for the entity using Reflection + /// + /// Type of the entity + /// Name of the attribute + public static string GetPrimaryKeyField(Type entityType) + { + if (entityType == null) + { + throw new ArgumentNullException("entityType"); + } + + foreach (PropertyInfo prop in entityType.GetProperties()) + { + if (prop.PropertyType == typeof(Guid?)) + { + return prop.Name; + } + } + + throw new ArgumentException("Does not contain property of type Key", "entityType"); + } + + private static object[] ConvertToObjectArray(IList list) + { + if (null == list || 0 == list.Count) + { + return new object[0]; + } + + //Create the array + object[] newArray = new object[list.Count]; + for (int i = 0; i < list.Count; i++) + { + newArray[i] = list[i]; + } + + return newArray; + } + + /// + /// Given the current organization, determine who the current user is + /// + /// Organization to connect to + /// Returns the object from the organization that is the current logged in user + public static CrmUser GetLoggedOnUser(CrmOrganization org) + { + WhoAmIResponse resp = (WhoAmIResponse)org.OrganizationService.Execute(new WhoAmIRequest()); + return org.Users[resp.UserId]; + } + + #endregion Private Helper Methods + + #region Private Classes + + private static class ParameterName + { + public const string EmailId = "EmailId"; + public const string EntityMoniker = "EntityMoniker"; + public const string Id = "Id"; + public const string SubordinateId = "SubordinateId"; + public const string Target = "Target"; + } + + #endregion Private Classes + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/OrganizationServiceExtensions.cs b/Ofscrm.PluginRegistration/Helpers/OrganizationServiceExtensions.cs new file mode 100644 index 0000000..f411d8f --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/OrganizationServiceExtensions.cs @@ -0,0 +1,59 @@ +using System; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Query; + +namespace Ofscrm.PluginRegistration.Helpers +{ + public static class OrganizationServiceExtensions + { + #region Public Methods + + /// + /// Retrieves all pages for a given query + /// + public static EntityCollection RetrieveMultipleAllPages(this IOrganizationService service, QueryBase query) + { + if (null == service) + { + throw new ArgumentNullException("service"); + } + else if (null == query) + { + throw new ArgumentNullException("query"); + } + + var fullResults = service.RetrieveMultiple(query); + if (!fullResults.MoreRecords) + { + return fullResults; + } + + var property = query.GetType().GetProperty("PageInfo"); + if (null == property) + { + throw new NotSupportedException("The specified query object does not have a PageInfo property defined."); + } + + var paging = new PagingInfo() { PageNumber = 1, ReturnTotalRecordCount = false }; + property.SetValue(query, paging, null); + + var results = fullResults; + while (results.MoreRecords) + { + //Update the paging information + paging.PagingCookie = results.PagingCookie; + paging.PageNumber++; + + //Retrieve the next page + results = service.RetrieveMultiple(query); + + //Add the results to the full list + fullResults.Entities.AddRange(results.Entities); + } + + return fullResults; + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Helpers/RegistrationHelper.cs b/Ofscrm.PluginRegistration/Helpers/RegistrationHelper.cs new file mode 100644 index 0000000..0687d88 --- /dev/null +++ b/Ofscrm.PluginRegistration/Helpers/RegistrationHelper.cs @@ -0,0 +1,1022 @@ +// ===================================================================== +// +// This file is part of the Microsoft Dynamics CRM SDK code samples. +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This source code is intended only as a supplement to Microsoft +// Development Tools and/or on-line documentation. See these other +// materials for detailed information regarding Microsoft code samples. +// +// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY +// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// ===================================================================== + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Query; +using Ofscrm.PluginRegistration.Entities; +using Ofscrm.PluginRegistration.Wrappers; + +namespace Ofscrm.PluginRegistration.Helpers +{ + public static class RegistrationHelper + { + #region Public Methods + + /// + /// Generate the default group name for an activity + /// + public static string GenerateDefaultGroupName(string assemblyName, Version version) + { + if (string.IsNullOrWhiteSpace(assemblyName)) + { + throw new ArgumentNullException("assemblyName"); + } + else if (null == version) + { + throw new ArgumentNullException("version"); + } + + return string.Format(CultureInfo.InvariantCulture, "{0} ({1})", assemblyName, version); + } + + /// + /// Generates a step description for the given message, primary and secondary entities, for a Step + /// + /// Name of the plug-in type + /// Message Name + /// Primary Entity + /// Secondary Entity + /// Description that the Step should use + public static string GenerateStepDescription(string typeName, string messageName, string primaryEntity, string secondaryEntity) + { + var descriptionBuilder = new StringBuilder(); + if (!string.IsNullOrWhiteSpace(typeName)) + { + descriptionBuilder.AppendFormat("{0}: ", typeName); + } + + if (string.IsNullOrEmpty(messageName)) + { + descriptionBuilder.Append("Not Specified of "); + } + else + { + descriptionBuilder.AppendFormat("{0} of ", messageName); + } + + bool hasPrimaryEntity = false; + if (!string.IsNullOrEmpty(primaryEntity) && + !string.Equals(primaryEntity, "none", StringComparison.InvariantCultureIgnoreCase)) + { + hasPrimaryEntity = true; + descriptionBuilder.Append(primaryEntity); + } + + if (!string.IsNullOrEmpty(secondaryEntity) && + !string.Equals(secondaryEntity, "none", StringComparison.InvariantCultureIgnoreCase)) + { + string format; + if (hasPrimaryEntity) + { + format = "and {0}"; + } + else + { + format = "{0}"; + } + + descriptionBuilder.AppendFormat(format, secondaryEntity); + } + else if (!hasPrimaryEntity) + { + descriptionBuilder.Append(" any Entity"); + } + + return descriptionBuilder.ToString(); + } + + /// + /// Determines if the given TypeName is in use for the given assembly id + /// + /// Organization to check + /// Type Name to check + /// Assembly that should contain the Type + /// pluginTypeId that is using the type name + /// True if the type name is found + public static bool PluginExists(CrmOrganization org, string typeName, Guid pluginAssemblyId, + out Guid pluginTypeId) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (typeName == null) + { + throw new ArgumentNullException("typeName"); + } + + QueryByAttribute query = new QueryByAttribute(PluginType.EntityLogicalName); + query.ColumnSet = new ColumnSet(); + query.AddAttributeValue("typename", typeName); + if (pluginAssemblyId != Guid.Empty) + { + query.AddAttributeValue("pluginassemblyid", pluginAssemblyId); + } + + var results = org.OrganizationService.RetrieveMultipleAllPages(query); + if (results.Entities != null && results.Entities.Count > 0) + { + pluginTypeId = results.Entities[0].Id; + return true; + } + else + { + pluginTypeId = Guid.Empty; + return false; + } + } + + public static Guid RegisterAssembly(CrmOrganization org, string pathToAssembly, CrmPluginAssembly assembly) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + else if (assembly.SourceType == CrmAssemblySourceType.Database && pathToAssembly == null) + { + throw new ArgumentNullException("pathToAssembly", "Cannot be null when SourceType is Database"); + } + + PluginAssembly ptl = (PluginAssembly)assembly.GenerateCrmEntities()[PluginAssembly.EntityLogicalName]; + if (assembly.SourceType == CrmAssemblySourceType.Database) + { + ptl.Content = Convert.ToBase64String(File.ReadAllBytes(pathToAssembly)); + } + + return org.OrganizationService.Create(ptl); + } + + public static Guid RegisterImage(CrmOrganization org, CrmPluginImage image) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (image == null) + { + throw new ArgumentNullException("image"); + } + return RegisterImage(org, image, org[image.AssemblyId][image.PluginId][image.StepId]); + } + + public static Guid RegisterImage(CrmOrganization org, CrmPluginImage image, CrmPluginStep step) + { + if (null == org) + { + throw new ArgumentNullException("org"); + } + else if (null == image) + { + throw new ArgumentNullException("image"); + } + else if (null == step) + { + throw new ArgumentNullException("step"); + } + + //Retrieve the SDK entity equivalent of the given image + Dictionary entityList = image.GenerateCrmEntities(step.MessageId, step.MessageEntityId); + SdkMessageProcessingStepImage sdkImage = (SdkMessageProcessingStepImage)entityList[SdkMessageProcessingStepImage.EntityLogicalName]; + + //If the step that owns this image is a profiled step, the step will be the original step (the step that is being profiled), + //not the profiler step. The Profiler step is what should be set on the server, since that is the step that is actually enabled. + if (step.IsProfiled && null != sdkImage.SdkMessageProcessingStepId) + { + sdkImage.SdkMessageProcessingStepId.Id = step.ProfilerStepId.GetValueOrDefault(); + } + + return org.OrganizationService.Create(sdkImage); + } + + public static Guid RegisterPlugin(CrmOrganization org, CrmPlugin plugin) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + + PluginType pt = (PluginType)plugin.GenerateCrmEntities()[PluginType.EntityLogicalName]; + + return org.OrganizationService.Create(pt); + } + + public static Guid RegisterServiceEndpoint(CrmOrganization org, CrmServiceEndpoint serviceEndpoint) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (serviceEndpoint == null) + { + throw new ArgumentNullException("serviceEndpoint"); + } + ServiceEndpoint sep = serviceEndpoint.GenerateCrmEntities()[ServiceEndpoint.EntityLogicalName] as ServiceEndpoint; + + return org.OrganizationService.Create(sep); + } + + public static Guid RegisterStep(CrmOrganization org, CrmPluginStep step) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (step == null) + { + throw new ArgumentNullException("step"); + } + + Dictionary entityList = step.GenerateCrmEntities(); + SdkMessageProcessingStep sdkStep = (SdkMessageProcessingStep)entityList[SdkMessageProcessingStep.EntityLogicalName]; + + //This is a sanity check. The UI won't allow a user to set the secure configuration. + if (org.SecureConfigurationPermissionDenied) + { + sdkStep.Attributes.Remove("sdkmessageprocessingstepsecureconfigid"); + sdkStep.RelatedEntities.Clear(); + } + else if (entityList.ContainsKey(Entities.SdkMessageProcessingStepSecureConfig.EntityLogicalName)) + { + Guid secureConfigId = Guid.NewGuid(); + + //Create the related secure config in the related entities + SdkMessageProcessingStepSecureConfig sdkSecureConfig = + (SdkMessageProcessingStepSecureConfig)entityList[SdkMessageProcessingStepSecureConfig.EntityLogicalName]; + sdkSecureConfig.Id = secureConfigId; + sdkStep.RelatedEntities[new Relationship(CrmPluginStep.RelationshipStepToSecureConfig)] = + new EntityCollection(new Entity[] { sdkSecureConfig }) { EntityName = sdkSecureConfig.LogicalName }; + step.SecureConfigurationId = secureConfigId; + } + + return org.OrganizationService.Create(sdkStep); + } + + /// + /// Extracts the properties for the plugin assembly + /// + /// Path to the DLL file that is needed to gather information + /// Properties Assembly + public static CrmPluginAssembly RetrieveAssemblyProperties(string pathToAssembly) + { + using (var context = new AppDomainContext()) + { + return context.Proxy.RetrieveAssemblyProperties(pathToAssembly); + } + } + + /// + /// Extracts all Workflow Activities and Plugins from the Assembly + /// + /// Path to the DLL file that is needed to gather information + /// List of Plugins in the Assembly + public static CrmPluginAssembly RetrievePluginsFromAssembly(string pathToAssembly) + { + using (var context = new AppDomainContext()) + { + return context.Proxy.RetrievePluginsFromAssembly(pathToAssembly); + } + } + + public static List RetrieveSecureConfigIdsForStepId(CrmOrganization org, IList stepIds) + { + return RetrieveReferenceAttributeIds(org, SdkMessageProcessingStep.EntityLogicalName, + "sdkmessageprocessingstepsecureconfigid", "sdkmessageprocessingstepid", stepIds); + } + + /// + /// Unregister entities and cascade the operation + /// + /// Organization to be used + /// Entities to be unregistered. If these are not invalid entities, only one can be specified + /// Cascade the operation + /// ProgressIndicator to indicate success + /// Statistics of what was unregistered + public static Dictionary Unregister(CrmOrganization org, params ICrmEntity[] crmEntity) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (crmEntity == null || crmEntity.Length == 0) + { + throw new ArgumentNullException("crmEntity"); + } + + var serviceEndpointList = new Collection(); + var assemblyList = new Collection(); + var pluginList = new Collection(); + var stepList = new Collection(); + var secureConfigList = new Collection(); + var imageList = new Collection(); + + //Create the list of various objects that need to be unregistered + foreach (var entity in crmEntity) + { + switch (entity.EntityType) + { + case ServiceEndpoint.EntityLogicalName: + serviceEndpointList.Add(entity.EntityId); + break; + + case PluginAssembly.EntityLogicalName: + assemblyList.Add(entity.EntityId); + break; + + case PluginType.EntityLogicalName: + pluginList.Add(entity.EntityId); + break; + + case SdkMessageProcessingStep.EntityLogicalName: + stepList.Add(entity.EntityId); + break; + + case SdkMessageProcessingStepImage.EntityLogicalName: + imageList.Add(entity.EntityId); + break; + + default: + throw new NotImplementedException("Type = " + entity.EntityType.ToString()); + } + } + + //Retrieve the up-to-date list of steps for the service endpoints and add them to the unregister list + foreach (var stepId in RetrieveStepIdsForServiceEndpoint(org, serviceEndpointList)) + { + if (!stepList.Contains(stepId)) + { + stepList.Add(stepId); + } + } + //Retrieve the up-to-date list of plugins for the assemblies and add them to the unregister list + foreach (var pluginId in RetrievePluginIdsForAssembly(org, assemblyList)) + { + if (!pluginList.Contains(pluginId)) + { + pluginList.Add(pluginId); + } + } + + //Retrieve the up-to-date list of steps for the plugins and add them to the unregister list + foreach (var stepId in RetrieveStepIdsForPlugins(org, pluginList)) + { + if (!stepList.Contains(stepId)) + { + stepList.Add(stepId); + } + } + + //Retrieve all of the profiler steps that need to be deleted + for (int i = stepList.Count - 1; i >= 0; i--) + { + CrmPluginStep step; + if (org.Steps.TryGetValue(stepList[i], out step)) + { + var profilerStepId = step.ProfilerStepId.GetValueOrDefault(); + if (Guid.Empty != profilerStepId && profilerStepId != step.StepId) + { + stepList.Add(profilerStepId); + } + } + } + + //Retrieve the up-to-date list of secure configs for the steps and add them to the unregister list + foreach (var secureConfigId in RetrieveSecureConfigIdsForStepId(org, stepList)) + { + if (!secureConfigList.Contains(secureConfigId)) + { + secureConfigList.Add(secureConfigId); + } + } + + //Retrieve the up-to-date list of images for the steps and add them to the unregister list + foreach (var imageId in RetrieveImageIdsForStepId(org, stepList)) + { + if (!imageList.Contains(imageId)) + { + imageList.Add(imageId); + } + } + + //Loop through each object and delete them + var deleteStats = new Dictionary(); + int totalSteps = secureConfigList.Count + 1; + if (serviceEndpointList.Count != 0) + { + deleteStats.Add(serviceEndpointList.Count == 1 ? "ServiceEndpoint" : "ServiceEndpoints", serviceEndpointList.Count); + totalSteps += serviceEndpointList.Count; + } + if (assemblyList.Count != 0) + { + deleteStats.Add(assemblyList.Count == 1 ? "Assembly" : "Assemblies", assemblyList.Count); + totalSteps += assemblyList.Count; + } + if (pluginList.Count != 0) + { + deleteStats.Add(pluginList.Count == 1 ? "Plugin" : "Plugins", pluginList.Count); + totalSteps += pluginList.Count; + } + if (stepList.Count != 0) + { + deleteStats.Add(stepList.Count == 1 ? "Step" : "Steps", stepList.Count); + totalSteps += stepList.Count; + } + if (imageList.Count != 0) + { + deleteStats.Add(imageList.Count == 1 ? "Image" : "Images", imageList.Count); + totalSteps += imageList.Count; + } + + foreach (var imageId in imageList) + { + org.OrganizationService.Delete(SdkMessageProcessingStepImage.EntityLogicalName, imageId); + } + + foreach (var stepId in stepList) + { + org.OrganizationService.Delete(SdkMessageProcessingStep.EntityLogicalName, stepId); + } + + foreach (Guid secureConfigId in secureConfigList) + { + org.OrganizationService.Delete(SdkMessageProcessingStepSecureConfig.EntityLogicalName, secureConfigId); + } + + foreach (var pluginId in pluginList) + { + org.OrganizationService.Delete(PluginType.EntityLogicalName, pluginId); + } + + foreach (var assemblyId in assemblyList) + { + org.OrganizationService.Delete(PluginAssembly.EntityLogicalName, assemblyId); + } + + foreach (var serviceEndpointId in serviceEndpointList) + { + org.OrganizationService.Delete(ServiceEndpoint.EntityLogicalName, serviceEndpointId); + } + + return deleteStats; + } + + /// + /// Assembly is Uploaded if it is database. + /// We dont do Smart updates + /// + /// + /// + /// + public static void UpdateAssembly(CrmOrganization org, string pathToAssembly, CrmPluginAssembly assembly, params PluginType[] type) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + var ptl = (PluginAssembly)assembly.GenerateCrmEntities()[PluginAssembly.EntityLogicalName]; + + //If the assembly path is not set, then the content does not need to be updated + if (!string.IsNullOrEmpty(pathToAssembly) && + assembly.SourceType == CrmAssemblySourceType.Database) + { + ptl.Content = Convert.ToBase64String(File.ReadAllBytes(pathToAssembly)); + } + + if (null != type && 0 != type.Length) + { + ptl.pluginassembly_plugintype = type; + } + + org.OrganizationService.Update(ptl); + OrganizationHelper.RefreshAssembly(org, assembly); + } + + public static void UpdateAssembly(CrmOrganization org, string description, Guid assemblyId) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (assemblyId == Guid.Empty) + { + throw new ArgumentNullException("assemblyId"); + } + + // Work around as updating only description is failing with publickeytoken not null + var pt1 = org.OrganizationService.Retrieve(PluginAssembly.EntityLogicalName, assemblyId, new ColumnSet(true)) as PluginAssembly; + //PluginAssembly pt1 = new PluginAssembly(); + pt1.Description = description; + org.OrganizationService.Update(pt1); + } + + public static void UpdateImage(CrmOrganization org, CrmPluginImage image) + { + if (null == org) + { + throw new ArgumentNullException("org"); + } + else if (null == image) + { + throw new ArgumentNullException("image"); + } + + UpdateImage(org, image, org[image.AssemblyId][image.PluginId][image.StepId]); + } + + public static void UpdateImage(CrmOrganization org, CrmPluginImage image, CrmPluginStep step) + { + if (null == org) + { + throw new ArgumentNullException("org"); + } + else if (null == image) + { + throw new ArgumentNullException("image"); + } + else if (null == step) + { + throw new ArgumentNullException("step"); + } + + //Retrieve the SDK entity equivalent of the given image + var entityList = image.GenerateCrmEntities(step.MessageId, step.MessageEntityId); + var sdkImage = (SdkMessageProcessingStepImage)entityList[SdkMessageProcessingStepImage.EntityLogicalName]; + + //If the step that owns this image is a profiled step, the step will be the original step (the step that is being profiled), + //not the profiler step. The Profiler step is what should be set on the server, since that is the step that is actually enabled. + if (step.IsProfiled && null != sdkImage.SdkMessageProcessingStepId) + { + sdkImage.SdkMessageProcessingStepId.Id = step.ProfilerStepId.GetValueOrDefault(); + } + + org.OrganizationService.Update(sdkImage); + OrganizationHelper.RefreshImage(org, image, step); + } + + public static void UpdatePlugin(CrmOrganization org, CrmPlugin plugin) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + + var ptl = (PluginType)plugin.GenerateCrmEntities()[PluginType.EntityLogicalName]; + + org.OrganizationService.Update(ptl); + OrganizationHelper.RefreshPlugin(org, plugin); + } + + public static void UpdatePlugin(CrmOrganization org, Guid pluginId, string typeName, string friendlyName) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + if (pluginId == Guid.Empty) + { + throw new ArgumentException("Invalid Guid", "pluginId"); + } + if (string.IsNullOrEmpty(typeName)) + { + throw new ArgumentException("Invalid typeName", "typeName"); + } + + if (friendlyName == null) + { + //No updates will occur if friendly name is null. Don't need to do anything + return; + } + + PluginType updatePlugin = new PluginType(); + + updatePlugin.PluginTypeId = new Guid?(); + updatePlugin["plugintypeid"] = pluginId; + + updatePlugin.FriendlyName = friendlyName; + updatePlugin.TypeName = typeName; + org.OrganizationService.Update(updatePlugin); + return; + } + + public static void UpdatePluginFriendlyName(CrmOrganization org, Guid pluginId, string friendlyName) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (pluginId == Guid.Empty) + { + throw new ArgumentException("Invalid Guid", "pluginId"); + } + else if (friendlyName == null) + { + //No updates will occur if friendly name is null. Don't need to do anything + return; + } + + PluginType updatePlugin = new PluginType(); + + updatePlugin.PluginTypeId = new Guid?(); + updatePlugin["plugintypeid"] = pluginId; + + updatePlugin.FriendlyName = friendlyName; + + org.OrganizationService.Update(updatePlugin); + return; + } + + public static void UpdateServiceEndpoint(CrmOrganization org, CrmServiceEndpoint serviceEndpoint) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (serviceEndpoint == null) + { + throw new ArgumentNullException("serviceEndpoint"); + } + var sep = serviceEndpoint.GenerateCrmEntities()[ServiceEndpoint.EntityLogicalName] as ServiceEndpoint; + + org.OrganizationService.Update(sep); + OrganizationHelper.RefreshServiceEndpoint(org, serviceEndpoint); + } + + public static bool UpdateStep(CrmOrganization org, CrmPluginStep step, Guid? origSecureConfigId, IList updateImages) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (step == null) + { + throw new ArgumentNullException("step"); + } + + var entityList = step.GenerateCrmEntities(); + var sdkStep = (SdkMessageProcessingStep)entityList[SdkMessageProcessingStep.EntityLogicalName]; + + // Loop through each image and set the new message property + List sdkImages = null; + if (null != updateImages) + { + // Ensure that the given message supports images + var message = org.Messages[step.MessageId]; + if (0 == message.ImageMessagePropertyNames.Count && step.Images.Count > 0) + { + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, + "The step has images registered, but the \"{0}\" message doesn't support images.{1}In order to change the message to \"{0}\", delete the existing images.", + message.Name, Environment.NewLine)); + } + + // Loop through the existing images and update their message property name values + sdkImages = new List(updateImages.Count); + foreach (CrmPluginImage image in updateImages) + { + // Set the message property name for each of the images + string propertyName = message.ImageMessagePropertyNames.FirstOrDefault()?.Name; + if (string.IsNullOrWhiteSpace(propertyName)) + { + return false; + } + else if (string.Equals(image.MessagePropertyName, propertyName, StringComparison.Ordinal)) + { + continue; + } + + // Create the entity to update the value + var sdkImage = new SdkMessageProcessingStepImage(); + sdkImage.Id = image.ImageId; + sdkImage.MessagePropertyName = propertyName; + sdkImage.EntityState = EntityState.Changed; + + sdkImages.Add(sdkImage); + } + } + + //This is a sanity check. The UI won't allow a user to set the secure configuration. + if (org.SecureConfigurationPermissionDenied) + { + sdkStep.Attributes.Remove("sdkmessageprocessingstepsecureconfigid"); + sdkStep.RelatedEntities.Clear(); + origSecureConfigId = null; + } + else if (entityList.ContainsKey(Entities.SdkMessageProcessingStepSecureConfig.EntityLogicalName)) + { + if (null == origSecureConfigId) + { + entityList.Remove(Entities.SdkMessageProcessingStepSecureConfig.EntityLogicalName); + } + else + { + SdkMessageProcessingStepSecureConfig sdkSecureConfig = + (SdkMessageProcessingStepSecureConfig)entityList[SdkMessageProcessingStepSecureConfig.EntityLogicalName]; + + Guid secureConfigId; + EntityState secureConfigState; + if (step.SecureConfigurationId == origSecureConfigId && origSecureConfigId.GetValueOrDefault() != Guid.Empty) + { + //Set the ID of the secure configuration to be the + secureConfigId = origSecureConfigId.GetValueOrDefault(); + secureConfigState = EntityState.Changed; + + //Set the original secure config id so that the current id is not deleted + sdkStep.SdkMessageProcessingStepSecureConfigId = + new EntityReference(SdkMessageProcessingStepSecureConfig.EntityLogicalName, secureConfigId); + } + else + { + secureConfigId = Guid.NewGuid(); + secureConfigState = EntityState.Created; + } + + //Set the configuration id for the step + step.SecureConfigurationId = secureConfigId; + + //Populate the secure configuration object and add it to the related entities + sdkSecureConfig.SdkMessageProcessingStepSecureConfigId = secureConfigId; + sdkSecureConfig.EntityState = secureConfigState; + + //Update the related entities + sdkStep.sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep = sdkSecureConfig; + + //Reset the original secure configuration + origSecureConfigId = null; + } + } + else if (null != origSecureConfigId) + { + // To null out if it was set before + sdkStep.SdkMessageProcessingStepSecureConfigId = null; + step.SecureConfigurationId = Guid.Empty; + + if (Guid.Empty == origSecureConfigId) + { + origSecureConfigId = null; + } + } + + // If the images need to be updated, there are two possible scenarios: + // 1) The step is profiled -- The parent of the image is not the step that is currently being updated + // but rather the profiler step itself. In order to avoid changing this, there will have to be two SDK + // operations (update the step and update the images). Otherwise, the next time the profiled step executes, + // the images won't be present. + // 2) The step is not profiled -- The image can be added to the related entities because the parent step is the + // current step being updated. + if (null != sdkImages && sdkImages.Count > 0) + { + if (!step.IsProfiled || step.ProfilerStepId == step.StepId) + { + sdkStep.sdkmessageprocessingstepid_sdkmessageprocessingstepimage = sdkImages; + } + } + + //Update the step + org.OrganizationService.Update(sdkStep); + + if (step.IsProfiled && null != sdkImages && sdkImages.Count > 0) + { + // Update the Profiler step with the new property values as a single transaction to minimize the + // possibility of data corruption. + SdkMessageProcessingStep profilerStep = new SdkMessageProcessingStep(); + profilerStep.Id = step.ProfilerStepId.GetValueOrDefault(); + profilerStep.sdkmessageprocessingstepid_sdkmessageprocessingstepimage = sdkImages; + org.OrganizationService.Update(profilerStep); + } + + // Refresh the objects so that the caller has up-to-date data + OrganizationHelper.RefreshStep(org, step); + if (null != updateImages) + { + foreach (CrmPluginImage image in updateImages) + { + OrganizationHelper.RefreshImage(org, image, step); + } + } + + // Delete the orphaned Secure config when nulling out the value on the step + if (null != origSecureConfigId) + { + org.OrganizationService.Delete(SdkMessageProcessingStepSecureConfig.EntityLogicalName, origSecureConfigId.GetValueOrDefault()); + } + + return true; + } + + public static void UpdateStepDescription(CrmOrganization org, Guid stepId, string description) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (stepId == Guid.Empty) + { + throw new ArgumentException("Invalid Guid", "stepId"); + } + else if (description == null) + { + //No updates will occur if description is null. Don't need to do anything + return; + } + + SdkMessageProcessingStep updateStep = new SdkMessageProcessingStep(); + + updateStep.SdkMessageProcessingStepId = new Guid?(); + updateStep["sdkmessageprocessingstepid"] = stepId; + + updateStep.Description = description; + + org.OrganizationService.Update(updateStep); + return; + } + + public static void UpdateStepStatus(CrmOrganization org, Guid stepId, bool isEnable) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (stepId == Guid.Empty) + { + throw new ArgumentException("Invalid Guid", "stepId"); + } + + Microsoft.Crm.Sdk.Messages.SetStateRequest request = new Microsoft.Crm.Sdk.Messages.SetStateRequest(); + request.EntityMoniker = new EntityReference(SdkMessageProcessingStep.EntityLogicalName, stepId); + if (isEnable) + { + request.State = new OptionSetValue((int)SdkMessageProcessingStepState.Enabled); + } + else + { + request.State = new OptionSetValue((int)SdkMessageProcessingStepState.Disabled); + } + request.Status = new OptionSetValue(-1); + org.OrganizationService.Execute(request); + + return; + } + + #endregion Public Methods + + #region Private Methods + + private static object[] ConvertIdArrayToObjectArray(IList idList) + { + if (idList == null) + { + return null; + } + + List newIdList = new List(); + if (idList != null && idList.Count != 0) + { + foreach (Guid id in idList) + { + if (id != Guid.Empty) + { + newIdList.Add(id); + } + } + } + + return newIdList.ToArray(); + } + + private static List RetrieveImageIdsForStepId(CrmOrganization org, IList stepIds) + { + return RetrieveReferenceAttributeIds(org, SdkMessageProcessingStepImage.EntityLogicalName, "sdkmessageprocessingstepimageid", "sdkmessageprocessingstepid", stepIds); + } + + private static List RetrievePluginIdsForAssembly(CrmOrganization org, IList assemblyIds) + { + return RetrieveReferenceAttributeIds(org, PluginType.EntityLogicalName, "plugintypeid", "pluginassemblyid", assemblyIds); + } + + /// + /// Retrieve the Id for each entityName that has a filterAttribute value in the filterIdList. + /// + private static List RetrieveReferenceAttributeIds(CrmOrganization org, string entityName, string retrieveAttribute, string filterAttribute, IList filterIdList) + { + #region Argument Validation + + if (org == null) + { + throw new ArgumentNullException("org"); + } + else if (entityName == null) + { + throw new ArgumentNullException("entityName"); + } + else if (retrieveAttribute == null) + { + throw new ArgumentNullException("retrieveAttribute"); + } + else if (filterAttribute == null) + { + throw new ArgumentNullException("filterAttribute"); + } + else if (retrieveAttribute == filterAttribute) + { + throw new ArgumentException("Attributes must be different"); + } + + #endregion Argument Validation + + if (filterIdList.Count == 0) + { + return new List(); + } + + //Generate the query + var cols = new ColumnSet(); + cols.AddColumns(retrieveAttribute); + + var idCondition = new ConditionExpression(); + idCondition.AttributeName = filterAttribute; + idCondition.Operator = ConditionOperator.In; + idCondition.Values.Clear(); + idCondition.Values.AddRange(ConvertIdArrayToObjectArray(filterIdList)); + + var query = new QueryExpression(); + query.ColumnSet = cols; + query.Criteria.AddCondition(idCondition); + query.EntityName = entityName; + + //Loop through the results + var resultList = new List(); + foreach (var entity in org.OrganizationService.RetrieveMultipleAllPages(query).Entities) + { + foreach (KeyValuePair prop in entity.Attributes) + { + if (prop.Key == retrieveAttribute) + { + var propType = prop.Value.GetType(); + if (propType == typeof(Guid)) + { + resultList.Add((Guid)prop.Value); + } + else if (propType == typeof(EntityReference)) + { + resultList.Add(((EntityReference)prop.Value).Id); + } + else + { + throw new ArgumentException("Unknown property returned " + prop.GetType().FullName); + } + } + } + } + + return resultList; + } + + private static List RetrieveStepIdsForPlugins(CrmOrganization org, IList pluginIds) + { + return RetrieveReferenceAttributeIds(org, SdkMessageProcessingStep.EntityLogicalName, "sdkmessageprocessingstepid", "plugintypeid", pluginIds); + } + + private static List RetrieveStepIdsForServiceEndpoint(CrmOrganization org, IList serviceEndpointIds) + { + return RetrieveReferenceAttributeIds(org, SdkMessageProcessingStep.EntityLogicalName, "sdkmessageprocessingstepid", "eventhandler", serviceEndpointIds); + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Ofscrm.PluginRegistration.csproj b/Ofscrm.PluginRegistration/Ofscrm.PluginRegistration.csproj new file mode 100644 index 0000000..508a7a1 --- /dev/null +++ b/Ofscrm.PluginRegistration/Ofscrm.PluginRegistration.csproj @@ -0,0 +1,134 @@ + + + + + Debug + AnyCPU + {48FC78F2-E0DA-4B04-B043-C69E9130A6A4} + Library + Properties + Ofscrm.PluginRegistration + Ofscrm.PluginRegistration + v4.5.2 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\MscrmTools.Xrm.Connection.1.2017.5.14\lib\net452\McTools.Xrm.Connection.dll + + + ..\packages\MscrmTools.Xrm.Connection.1.2017.5.14\lib\net452\McTools.Xrm.Connection.WinForms.dll + + + ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0\lib\net45\Microsoft.Crm.Sdk.Proxy.dll + + + ..\packages\Microsoft.IdentityModel.6.1.7600.16394\lib\net35\Microsoft.IdentityModel.dll + True + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll + + + ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0\lib\net45\Microsoft.Xrm.Sdk.dll + + + ..\packages\Microsoft.CrmSdk.Deployment.8.2.0\lib\net45\Microsoft.Xrm.Sdk.Deployment.dll + + + ..\packages\Microsoft.CrmSdk.Workflow.8.2.0\lib\net45\Microsoft.Xrm.Sdk.Workflow.dll + + + ..\packages\Microsoft.CrmSdk.XrmTooling.CoreAssembly.8.2.0.5\lib\net452\Microsoft.Xrm.Tooling.Connector.dll + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + ..\packages\System.ValueTuple.4.3.1\lib\netstandard1.0\System.ValueTuple.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Properties/AssemblyInfo.cs b/Ofscrm.PluginRegistration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1414c41 --- /dev/null +++ b/Ofscrm.PluginRegistration/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("Ofscrm.PluginRegistration")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Ofscrm.PluginRegistration")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 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("48fc78f2-e0da-4b04-b043-c69e9130a6a4")] + +// 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/Ofscrm.PluginRegistration/UpdatePluginsCommand.cs b/Ofscrm.PluginRegistration/UpdatePluginsCommand.cs new file mode 100644 index 0000000..dc4a51f --- /dev/null +++ b/Ofscrm.PluginRegistration/UpdatePluginsCommand.cs @@ -0,0 +1,634 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Ofscrm.PluginRegistration.Helpers; +using Ofscrm.PluginRegistration.Wrappers; + +namespace Ofscrm.PluginRegistration +{ + public class UpdatePluginsCommand : CommandBase + { + private readonly List _assemblies; + private readonly UpdatePluginsCommandOptions _options; + + public UpdatePluginsCommand(UpdatePluginsCommandOptions options) + { + _options = options; + _assemblies = new List(); + + foreach (CrmPluginAssembly assembly in Organization.Assemblies) + { + // If the same assembly name used for any other custom plugin assembly then that need to be added + if ((CrmServiceEndpoint.ServiceBusPluginAssemblyName != assembly.Name || 0 != assembly.CustomizationLevel) && + !assembly.IsProfilerAssembly) + { + _assemblies.Add(assembly); + } + } + } + + public void ExecuteCommand() + { + // for each plugin registered in the system + // check the plugin load folder for available matching assemblies + var newAssemblies = _assemblies + .Select(GetPluginAssemblyFromPluginFolder) + .Where(assemblyCouple => assemblyCouple.localAssembly != null).ToList(); + + // for each matching assemblies we execute the assembly update + // and the plugin update + foreach ((CrmPluginAssembly crmAssembly, CrmPluginAssembly localAssembly) assemblyCouple in newAssemblies) + { + RegisterPlugin(assemblyCouple.crmAssembly, assemblyCouple.localAssembly); + } + } + + private (CrmPluginAssembly crmAssembly, CrmPluginAssembly localAssembly) GetPluginAssemblyFromPluginFolder(CrmPluginAssembly crmAssembly) + { + string assemblyFileName = Path.Combine(_options.PluginsFolder, crmAssembly.Name); + if (File.Exists(assemblyFileName) == false) return (crmAssembly, null); + + CrmPluginAssembly localAssembly; + try + { + localAssembly = RegistrationHelper.RetrievePluginsFromAssembly(assemblyFileName); + } + catch (Exception ex) + { + throw new Exception("Unable to load the specified Plugin Assembly", ex); + } + + return (crmAssembly, localAssembly); + } + + private void RegisterPlugin(CrmPluginAssembly crmAssembly, CrmPluginAssembly localAssembly) + { + + } + + private void btnRegister_Click(object sender, EventArgs e) + { + // Create a list of currently selected plugins + var assemblyCanBeIsolated = true; + var checkedPluginList = new Dictionary(); + + foreach (ICrmTreeNode node in trvPlugins.CheckedNodes) + { + if (node.NodeType == CrmTreeNodeType.Plugin || node.NodeType == CrmTreeNodeType.WorkflowActivity) + { + var plugin = (CrmPlugin)node; + if (CrmPluginIsolatable.No == plugin.Isolatable) + { + assemblyCanBeIsolated = false; + } + + checkedPluginList.Add(plugin.TypeName, plugin); + } + } + + //Check if there are any plugins selected + if (checkedPluginList.Count == 0) + { + MessageBox.Show( + "No plugins have been selected from the list. Please select at least one and try again.", + "No Plugins Selected", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + + // Verify that a valid isolation mode has been selected + if (radIsolationSandbox.Checked && !assemblyCanBeIsolated) + { + MessageBox.Show( + "Since some of the plug-ins cannot be isolated, the assembly cannot be marked as Isolated.", + "Isolation", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + + //Reload the assembly + var assemblyPath = AssemblyPathControl.FileName; + CrmPluginAssembly assembly; + if (string.IsNullOrEmpty(assemblyPath)) + { + // Clone the existing assembly + assembly = m_currentAssembly.Clone(false); + } + else + { + assembly = RegistrationHelper.RetrievePluginsFromAssembly(assemblyPath); + + //Retrieve the source type and determine if the + assembly.SourceType = GetAssemblySourceType(); + + if (CrmAssemblySourceType.Disk != assembly.SourceType) + { + assembly.ServerFileName = null; + } + else + { + assembly.ServerFileName = txtServerFileName.Text; + } + } + + if (m_currentAssembly != null) + { + var oldVersion = new Version(m_currentAssembly.Version); + var newVersion = new Version(assembly.Version); + + if (oldVersion.Major != newVersion.Major) + { + MessageBox.Show( + $"Assembly's major version has changed from {oldVersion} to {newVersion}.\n\nSuch an update is not supported, please register another instance of this assembly instead!", + "Assembly's version missmatch", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + + if (oldVersion.Minor != newVersion.Minor) + { + MessageBox.Show( + $"Assembly's minor version has changed from {oldVersion} to {newVersion}.\n\nSuch an update is not supported, please register another instance of this assembly instead!", + "Assembly's version missmatch", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + } + + // Ensure the checked items were all found in the assembly + var registerPluginList = new List(); + var pluginList = new List(); + var removedPluginList = new List(); + var missingPluginList = new List(); + + try + { + Parallel.ForEach(assembly.Plugins.Values, (currentPlugin) => { + var foundPlugin = m_registeredPluginList?.Where(x => x.TypeName.ToLowerInvariant() == currentPlugin.TypeName.ToLowerInvariant()).FirstOrDefault(); + var alreadyExisted = (m_registeredPluginList != null && foundPlugin != null); + + if (alreadyExisted) + { + currentPlugin.AssemblyId = m_currentAssembly.AssemblyId; + currentPlugin.PluginId = foundPlugin.PluginId; + } + + if (checkedPluginList.ContainsKey(currentPlugin.TypeName)) + { + registerPluginList.Add(currentPlugin); + + if (currentPlugin.PluginType == CrmPluginType.Plugin) + { + pluginList.Add(currentPlugin); + } + } + else if (alreadyExisted) + { + removedPluginList.Add(currentPlugin); + } + }); + + if (m_registeredPluginList != null) + { + Parallel.ForEach(m_registeredPluginList, (currentRecord) => { + if (!assembly.Plugins.Values.ToList().Any(x => x.TypeName.ToLowerInvariant() == currentRecord.TypeName.ToLowerInvariant())) + { + missingPluginList.Add(currentRecord); + } + }); + } + } + catch (Exception ex) + { + ErrorMessageForm.ShowErrorMessageBox(this, "Unable to load the specified Plugin Assembly.", "Plugins", ex); + return; + } + + // Update the assembly with the information specified by the user + assembly.IsolationMode = GetIsolationMode(); + + if (missingPluginList.Count != 0) + { + var list = missingPluginList.Select(x => x.TypeName).Aggregate((name01, name02) => name01 + "\n" + name02); + + MessageBox.Show( + $"Following plugin are missing in the assembly:\n\n{list}\n\nRegistration cannot continue!", + "Plugins are missing", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + + // An assembly with plugins must be strongly signed + if (pluginList.Count != 0) + { + if (string.IsNullOrEmpty(assembly.PublicKeyToken)) + { + MessageBox.Show( + "Assemblies containing Plugins must be strongly signed. Sign the Assembly using a KeyFile.", + "Strong Names Error", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + } + + // Check if there are any plugins selected that were in the assembly. + if (registerPluginList.Count == 0) + { + MessageBox.Show( + "No plugins have been selected from the list. Please select at least one and try again.", + "No Plugins Selected", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + + return; + } + else + { + assembly.ClearPlugins(); + } + + // If we are doing an Update, do some special processing + if (m_currentAssembly != null) + { + assembly.AssemblyId = m_currentAssembly.AssemblyId; + } + #endregion + + #region Register Plugin + m_progRegistration.Initialize(registerPluginList.Count + removedPluginList.Count, "Preparing Registration"); + + int registeredAssemblies = 0; + int ignoredAssemblies = 0; + int updatedAssemblies = 0; + bool createAssembly; + + //Check whether the plugin exists. If it exists, should we use the existing one? + var retrieveDateList = new List(); + try + { + Guid pluginAssemblyId = Guid.Empty; + if (m_currentAssembly != null) + { + if (chkUpdateAssembly.Checked) + { + var originalGroupName = RegistrationHelper.GenerateDefaultGroupName(m_currentAssembly.Name, new Version(m_currentAssembly.Version)); + var newGroupName = RegistrationHelper.GenerateDefaultGroupName(assembly.Name, new Version(assembly.Version)); + + var updateGroupNameList = new List(); + foreach (var plugin in m_currentAssembly.Plugins) + { + if (plugin.PluginType == CrmPluginType.WorkflowActivity && string.Equals(plugin.WorkflowActivityGroupName, originalGroupName)) + { + updateGroupNameList.Add(new PluginType() + { + Id = plugin.PluginId, + WorkflowActivityGroupName = newGroupName + }); + } + } + + //Do the actual update to the assembly + RegistrationHelper.UpdateAssembly(m_org, assemblyPath, assembly, updateGroupNameList.ToArray()); + + m_currentAssembly.Name = assembly.Name; + m_currentAssembly.Culture = assembly.Culture; + m_currentAssembly.CustomizationLevel = assembly.CustomizationLevel; + m_currentAssembly.PublicKeyToken = assembly.PublicKeyToken; + m_currentAssembly.ServerFileName = assembly.ServerFileName; + m_currentAssembly.SourceType = assembly.SourceType; + m_currentAssembly.Version = assembly.Version; + m_currentAssembly.IsolationMode = assembly.IsolationMode; + + retrieveDateList.Add(m_currentAssembly); + + foreach (var type in updateGroupNameList) + { + var plugin = m_currentAssembly.Plugins[type.Id]; + + plugin.WorkflowActivityGroupName = type.WorkflowActivityGroupName; + retrieveDateList.Add(plugin); + } + + updatedAssemblies++; + } + else if (!chkUpdateAssembly.Visible && assembly.IsolationMode != m_currentAssembly.IsolationMode) + { + var updateAssembly = new PluginAssembly() + { + Id = assembly.AssemblyId, + IsolationMode = new OptionSetValue((int)assembly.IsolationMode) + }; + + m_org.OrganizationService.Update(updateAssembly); + + m_currentAssembly.ServerFileName = assembly.ServerFileName; + m_currentAssembly.SourceType = assembly.SourceType; + m_currentAssembly.IsolationMode = assembly.IsolationMode; + + retrieveDateList.Add(m_currentAssembly); + + updatedAssemblies++; + } + + assembly = m_currentAssembly; + + createAssembly = false; + m_progRegistration.Increment(); + + m_orgControl.RefreshAssembly(m_currentAssembly, false); + } + else + { + createAssembly = true; + m_progRegistration.Increment(); + } + } + catch (Exception ex) + { + if (!string.IsNullOrEmpty(ex.Message)) + { + ERROR_MESSAGE = ex.Message; + } + + m_progRegistration.Increment($"ERROR: {ERROR_MESSAGE}"); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + m_progRegistration.Complete(false); + return; + } + + //Register the assembly (if needed) + if (createAssembly) + { + try + { + assembly.AssemblyId = RegistrationHelper.RegisterAssembly(m_org, assemblyPath, assembly); + assembly.Organization = m_org; + + retrieveDateList.Add(assembly); + } + catch (Exception ex) + { + var chunks = ex.Message.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries); + + if (chunks.Length > 1) + { + // Replacing generic error message extracted from exception to the title of the window + ERROR_MESSAGE = chunks[chunks.Length - 1]; + } + + m_progRegistration.Increment($"ERROR: {ERROR_MESSAGE}"); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + m_progRegistration.Complete(false); + return; + } + + registeredAssemblies++; + m_progRegistration.Increment("SUCCESS: Plugin Assembly was registered"); + } + else if (m_currentAssembly == null) + { + ignoredAssemblies++; + m_progRegistration.Increment("INFORMATION: Assembly was not registered"); + } + else + { + if (chkUpdateAssembly.Checked) + { + m_progRegistration.Increment("SUCCESS: Assembly was updated"); + } + else + { + m_progRegistration.Increment("INFORMATION: Assembly was not updated"); + } + } + + //Check to see if the assembly needs to be added to the list + if (!m_org.Assemblies.ContainsKey(assembly.AssemblyId)) + { + m_org.AddAssembly(assembly); + + //Update the Main Form + try + { + m_orgControl.AddAssembly(assembly); + m_progRegistration.Increment(); + } + catch (Exception ex) + { + m_progRegistration.Increment("ERROR: Error occurred while updating the Main form for the assembly"); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + m_progRegistration.Complete(false); + return; + } + } + else + { + m_progRegistration.Increment(); + } + + // Register the Plugin + bool createPlugin; + int registeredPlugins = 0; + int ignoredPlugins = 0; + int errorsPlugins = 0; + + foreach (var currentPlugin in registerPluginList) + { + currentPlugin.AssemblyId = assembly.AssemblyId; + + //Check if the plugin exists + bool pluginUpdate = m_registeredPluginList != null && m_registeredPluginList.Any(x => x.TypeName.ToLowerInvariant() == currentPlugin.TypeName.ToLowerInvariant()); + try + { + Guid pluginTypeId = Guid.Empty; + + if (pluginUpdate || (!createAssembly && RegistrationHelper.PluginExists(m_org, currentPlugin.TypeName, assembly.AssemblyId, out pluginTypeId))) + { + if (pluginUpdate) + { + createPlugin = false; + } + else + { + m_progRegistration.AppendText(string.Format("INFORMATION: Plugin Type Name is already being used by PluginType {0}.", pluginTypeId)); + + switch (MessageBox.Show(string.Format("The specified name \"{0}\" is already registered. Skip the registration of this plugin?\n\nPlease note the plugins may not be the same.", currentPlugin.TypeName), + "Plugin Already Exists", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)) + { + case DialogResult.Yes: + createPlugin = false; + + currentPlugin.PluginId = pluginTypeId; + currentPlugin.Organization = assembly.Organization; + break; + case DialogResult.No: + createPlugin = true; + break; + case DialogResult.Cancel: + m_progRegistration.AppendText("ABORTED: Plugin Registration has been aborted by the user."); + m_progRegistration.Complete(false); + return; + default: + throw new NotImplementedException(); + } + } + + m_progRegistration.Increment(); + } + else + { + createPlugin = true; + m_progRegistration.Increment(); + } + } + catch (Exception ex) + { + m_progRegistration.Increment(string.Format("ERROR: Occurred while checking if {0} is already registered.", + currentPlugin.TypeName)); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + m_progRegistration.Complete(false); + return; + } + + //Create the plugin (if necessary) + if (createPlugin) + { + try + { + Guid pluginId = currentPlugin.PluginId; + currentPlugin.PluginId = RegistrationHelper.RegisterPlugin(m_org, currentPlugin); + currentPlugin.Organization = m_org; + + if (pluginId != currentPlugin.PluginId && assembly.Plugins.ContainsKey(pluginId)) + { + assembly.RemovePlugin(pluginId); + } + + retrieveDateList.Add(currentPlugin); + + m_progRegistration.Increment(string.Format("SUCCESS: Plugin {0} was registered.", + currentPlugin.TypeName)); + + registeredPlugins++; + } + catch (Exception ex) + { + m_progRegistration.Increment(2, string.Format("ERROR: Occurred while registering {0}.", + currentPlugin.TypeName)); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + errorsPlugins++; + continue; + } + } + else + { + if (!pluginUpdate) + { + ignoredPlugins++; + } + + m_progRegistration.Increment(); + } + + //Check if the plugin needs to be added to the list + if (!assembly.Plugins.ContainsKey(currentPlugin.PluginId)) + { + assembly.AddPlugin(currentPlugin); + + //Update the main form + try + { + m_orgControl.AddPlugin(currentPlugin); + m_progRegistration.Increment(); + } + catch (Exception ex) + { + m_progRegistration.Increment(string.Format("ERROR: Occurred while updating the Main form for {0}.", + currentPlugin.TypeName)); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + m_progRegistration.Complete(false); + return; + } + } + else + { + m_progRegistration.Increment(); + } + } + + // Unregister plugins that were unchecked + int updatedPlugins = 0; + foreach (var currectPlugin in removedPluginList) + { + //Check if the plugin exists + try + { + RegistrationHelper.Unregister(m_org, currectPlugin); + m_progRegistration.Increment(3, string.Format("SUCCESS: Plugin {0} was unregistered.", currectPlugin.TypeName)); + m_orgControl.RemovePlugin(currectPlugin.PluginId); + + updatedPlugins++; + } + catch (Exception ex) + { + m_progRegistration.Increment(3, string.Format("ERROR: Occurred while unregistering {0}.", currectPlugin.TypeName)); + + ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex); + + errorsPlugins++; + } + } + + //Update the entities whose Created On / Modified On dates changed + try + { + OrganizationHelper.UpdateDates(m_org, retrieveDateList); + m_progRegistration.Increment("SUCCESS: Created On / Modified On dates updated"); + } + catch (Exception ex) + { + m_progRegistration.Increment("ERROR: Unable to update Created On / Modified On dates"); + + ErrorMessageForm.ShowErrorMessageBox(this, "Unable to update Created On / Modified On dates", "Update Error", ex); + } + #endregion + + m_progRegistration.AppendText("SUCCESS: Selected Plugins have been registered"); + m_progRegistration.Complete(false); + + MessageBox.Show(string.Format("The selected Plugins have been registered.\n{0} Assembly Registered\n{1} Assembly Ignored\n{2} Assembly Updated\n{3} Plugin(s) Registered\n{4} Plugin(s) Ignored\n{5} Plugin(s) Encountered Errors\n{6} Plugin(s) Removed", + registeredAssemblies, ignoredAssemblies, updatedAssemblies, registeredPlugins, ignoredPlugins, errorsPlugins, updatedPlugins), + "Registered Plugins", MessageBoxButtons.OK, MessageBoxIcon.Information); + + if (errorsPlugins == 0) + { + Close(); + } + } + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/UpdatePluginsCommandOptions.cs b/Ofscrm.PluginRegistration/UpdatePluginsCommandOptions.cs new file mode 100644 index 0000000..ff89e88 --- /dev/null +++ b/Ofscrm.PluginRegistration/UpdatePluginsCommandOptions.cs @@ -0,0 +1,7 @@ +namespace Ofscrm.PluginRegistration +{ + public class UpdatePluginsCommandOptions + { + public string PluginsFolder { get; set; } + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmAttribute.cs b/Ofscrm.PluginRegistration/Wrappers/CrmAttribute.cs new file mode 100644 index 0000000..0afac12 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmAttribute.cs @@ -0,0 +1,129 @@ +using System; +using Microsoft.Xrm.Sdk.Metadata; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public sealed class CrmAttribute + { + #region Private Fields + + private AttributeTypeCode m_attributeType; + private string m_friendlyName; + private bool m_isPrimaryId = false; + private string m_schemaName; + private bool m_validForCreate = false; + private bool m_validForRead = false; + private bool m_validForUpdate = false; + + #endregion Private Fields + + #region Public Constructors + + public CrmAttribute(string schemaName, string friendlyName, AttributeTypeCode type, + bool validForCreate, bool validForUpdate, bool validForRead, bool isPrimaryId) + { + if (schemaName == null) + { + throw new ArgumentNullException("schemaName"); + } + else if (friendlyName == null) + { + throw new ArgumentNullException("friendlyName"); + } + + m_schemaName = schemaName; + m_friendlyName = friendlyName; + m_attributeType = type; + m_validForCreate = validForCreate; + m_validForRead = validForRead; + m_validForUpdate = validForUpdate; + m_isPrimaryId = isPrimaryId; + } + + public CrmAttribute(AttributeMetadata md, bool isPrimaryId) + { + if (md == null) + { + throw new ArgumentNullException("md"); + } + + m_schemaName = md.LogicalName; + if (md.DisplayName.LocalizedLabels.Count == 0) + { + m_friendlyName = md.LogicalName; + } + else + { + m_friendlyName = md.DisplayName.UserLocalizedLabel.Label; + } + + m_attributeType = md.AttributeType.Value; + m_validForCreate = md.IsValidForCreate.Value; + m_validForRead = md.IsValidForUpdate.Value; + m_validForUpdate = md.IsValidForUpdate.Value; + m_isPrimaryId = isPrimaryId; + } + + #endregion Public Constructors + + #region Public Properties + + public string FriendlyName + { + get + { + return m_friendlyName; + } + } + + public bool IsPrimaryId + { + get + { + return m_isPrimaryId; + } + } + + public string LogicalName + { + get + { + return m_schemaName; + } + } + + public AttributeTypeCode Type + { + get + { + return m_attributeType; + } + } + + public bool ValidForCreate + { + get + { + return m_validForCreate; + } + } + + public bool ValidForRead + { + get + { + return m_validForRead; + } + } + + public bool ValidForUpdate + { + get + { + return m_validForUpdate; + } + } + + #endregion Public Properties + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmEntityDictionary.cs b/Ofscrm.PluginRegistration/Wrappers/CrmEntityDictionary.cs new file mode 100644 index 0000000..4252277 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmEntityDictionary.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public class CrmEntityDictionary : IEnumerable, IEnumerable + where EntityType : ICrmEntity + { + #region Private Fields + + private Dictionary m_entityList = new Dictionary(); + + #endregion Private Fields + + #region Public Constructors + + public CrmEntityDictionary(Dictionary entityList) + { + if (entityList == null) + { + throw new ArgumentNullException("entityList"); + } + + m_entityList = entityList; + } + + #endregion Public Constructors + + #region Public Properties + + public int Count + { + get + { + return m_entityList.Count; + } + } + + public Dictionary.KeyCollection Keys + { + get + { + return m_entityList.Keys; + } + } + + public Dictionary.ValueCollection Values + { + get + { + return m_entityList.Values; + } + } + + #endregion Public Properties + + #region Public Indexers + + public EntityType this[Guid id] + { + get + { + return m_entityList[id]; + } + } + + #endregion Public Indexers + + #region Public Methods + + public bool ContainsKey(Guid id) + { + return m_entityList.ContainsKey(id); + } + + public IEnumerator GetEnumerator() + { + return m_entityList.Values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return m_entityList.Values.GetEnumerator(); + } + + public EntityType[] ToArray() + { + EntityType[] items = new EntityType[m_entityList.Count]; + m_entityList.Values.CopyTo(items, 0); + + return items; + } + + public bool TryGetValue(Guid id, out EntityType value) + { + return m_entityList.TryGetValue(id, out value); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmMessage.cs b/Ofscrm.PluginRegistration/Wrappers/CrmMessage.cs new file mode 100644 index 0000000..ff66df6 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmMessage.cs @@ -0,0 +1,569 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public sealed class CrmMessage : ICrmEntity + { + #region Private Fields + + private static CrmEntityColumn[] m_entityColumns = null; + private DateTime? m_createdOn = null; + private int m_customizationLevel = 0; + private Dictionary m_filterList = new Dictionary(); + private CrmEntityDictionary m_filterReadOnlyList = null; + private Guid m_messageId = Guid.Empty; + private string m_messageName = null; + private List m_messagePropertyNames; + private DateTime? m_modifiedOn = null; + private CrmOrganization m_org; + private bool m_supportsFilteredAttributes = false; + + #endregion Private Fields + + #region Public Constructors + + public CrmMessage(CrmOrganization org) + { + m_org = org; + } + + public CrmMessage(CrmOrganization org, Guid messageId, string messageName, bool supportsFilteredAttributes, + int customizationLevel, DateTime? createdOn, DateTime? modifiedOn, + List imageMessagePropertyNames) + : this(org) + { + MessageId = messageId; + Name = messageName; + CustomizationLevel = customizationLevel; + SupportsFilteredAttributes = supportsFilteredAttributes; + UpdateDates(createdOn, modifiedOn); + + m_messagePropertyNames = imageMessagePropertyNames; + } + + public CrmMessage(CrmOrganization org, SdkMessage msg) + : this(org) + { + RefreshFromSdkMessage(msg); + } + + #endregion Public Constructors + + #region Public Properties + + [XmlIgnore, Browsable(false)] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Id", null, typeof(Guid)), + new CrmEntityColumn("Name", "Name", typeof(string)) }; + } + + return m_entityColumns; + } + } + + /// + /// Retrieves the Created On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn + { + get + { + return m_createdOn; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int CustomizationLevel + { + get + { + return m_customizationLevel; + } + set + { + m_customizationLevel = value; + } + } + + [XmlIgnore, Browsable(false)] + public Guid EntityId + { + get + { + return MessageId; + } + } + + [XmlIgnore, Browsable(false)] + public string EntityType + { + get + { + return SdkMessageFilter.EntityLogicalName; + } + } + + [Browsable(false)] + public List ImageMessagePropertyNames + { + get + { + if (null == m_messagePropertyNames) + { + m_messagePropertyNames = new List(); + } + + return m_messagePropertyNames; + } + } + + [XmlIgnore, Browsable(false)] + public bool IsSystemCrmEntity + { + get + { + return (m_customizationLevel == 0); + } + } + + [Browsable(false)] + public CrmEntityDictionary MessageEntities + { + get + { + if (m_filterReadOnlyList == null) + { + m_filterReadOnlyList = new CrmEntityDictionary(m_filterList); + } + + return m_filterReadOnlyList; + } + } + + [Category("Information"), Browsable(true), Description("Unique identifier of Message"), ReadOnly(true)] + public Guid MessageId + { + get + { + return m_messageId; + } + + set + { + m_messageId = value; + } + } + + /// + /// Retrieves the Modified On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn + { + get + { + return m_modifiedOn; + } + } + + [Category("Information"), Browsable(true), Description("Name of the Message"), ReadOnly(true)] + public string Name + { + get + { + return m_messageName; + } + + set + { + m_messageName = value; + } + } + + [Browsable(false)] + public CrmOrganization Organization + { + get + { + return m_org; + } + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + else if (m_org == null) + { + m_org = value; + + foreach (CrmMessageEntity entity in m_filterList.Values) + { + Organization.AddMessageEntity(this, entity); + } + } + else + { + throw new NotSupportedException("Cannot change the Organization once it has been set"); + } + } + } + + [Browsable(false)] + public bool SupportsFilteredAttributes + { + get + { + return m_supportsFilteredAttributes; + } + + set + { + m_supportsFilteredAttributes = value; + } + } + + [XmlIgnore, Browsable(false)] + public Dictionary Values + { + get + { + var valueList = new Dictionary(); + valueList.Add("Id", MessageId); + valueList.Add("Name", Name); + + return valueList; + } + } + + #endregion Public Properties + + #region Public Indexers + + [Browsable(false)] + public CrmMessageEntity this[Guid filterId] + { + get + { + return m_filterList[filterId]; + } + } + + #endregion Public Indexers + + #region Public Methods + + public void AddMessageEntity(CrmMessageEntity entity) + { + if (entity == null) + { + throw new ArgumentNullException("entity"); + } + + m_filterList.Add(entity.MessageEntityId, entity); + + if (Organization != null) + { + Organization.AddMessageEntity(this, entity); + } + } + + public void ClearMessageEntities() + { + m_filterList.Clear(); + + if (Organization != null) + { + Organization.ClearMessageEntities(MessageId); + } + } + + /// + /// Locate the message entities based on the primary or secondary entity (or both) + /// + /// Returns all CrmMessageEntity that match the criteria + public CrmMessageEntity[] FindMessageEntities(string primaryEntity, string secondaryEntity) + { + return FindMessageEntities(primaryEntity, secondaryEntity, true).ToArray(); + } + + /// + /// Locate the message entity based on the primary or secondary entity (or both) + /// + /// First CrmMessageEntity that matches the criteria + public CrmMessageEntity FindMessageEntity(string primaryEntity, string secondaryEntity) + { + if (string.IsNullOrEmpty(primaryEntity) && string.IsNullOrEmpty(secondaryEntity)) + { + return null; + } + List matchList = FindMessageEntities(primaryEntity, secondaryEntity, true); + if (matchList == null || matchList.Count == 0) + { + return null; + } + else + { + return matchList[0]; + } + } + + public Dictionary GenerateCrmEntities() + { + var entityList = new Dictionary(); + + var entity = new SdkMessage(); + + entity.SdkMessageId = new Guid?(); + entity["sdkmessageid"] = MessageId; + + if (!string.IsNullOrEmpty(Name)) + { + entity.Name = Name; + } + + entityList.Add(SdkMessage.EntityLogicalName, entity); + + return entityList; + } + + public void RefreshFromSdkMessage(SdkMessage msg) + { + if (msg == null) + { + throw new ArgumentNullException("msg"); + } + + if (msg.SdkMessageId != null) + { + MessageId = msg.SdkMessageId.Value; + } + + if (msg.Name != null) + { + Name = msg.Name; + } + + if (msg.CustomizationLevel != null) + { + CustomizationLevel = msg.CustomizationLevel.Value; + } + + if (msg.CreatedOn != null && (msg.CreatedOn.HasValue)) + { + m_createdOn = msg.CreatedOn.Value; + } + + if (msg.ModifiedOn != null && (msg.ModifiedOn.HasValue)) + { + m_modifiedOn = msg.ModifiedOn.Value; + } + } + + public void RemoveMessageEntity(Guid messageEntityId) + { + if (m_filterList.ContainsKey(messageEntityId)) + { + m_filterList.Remove(messageEntityId); + + if (Organization != null) + { + Organization.RemoveMessageEntity(this, messageEntityId); + } + } + else + { + throw new ArgumentException("Invalid Message Entity Id", "messageEntityId"); + } + } + + public override string ToString() + { + return string.Format(System.Globalization.CultureInfo.InvariantCulture, "(Message) {0}", Name); + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + m_createdOn = createdOn; + } + + if (modifiedOn != null) + { + m_modifiedOn = modifiedOn; + } + } + + #endregion Public Methods + + #region Private Methods + + /// + /// primaryEntity = NULL and secondaryEntity = null shall return complete list of entities. + /// + /// + /// + /// + /// + private List FindMessageEntities(string primaryEntity, string secondaryEntity, + bool stopAtFirstMatch) + { + bool hasNoneNone = false; + var msgList = new List(); + + bool findNoneNone; + if ((string.IsNullOrEmpty(primaryEntity) || primaryEntity.Equals("none", StringComparison.InvariantCultureIgnoreCase)) && + (string.IsNullOrEmpty(secondaryEntity) || secondaryEntity.Equals("none", StringComparison.InvariantCultureIgnoreCase))) + { + findNoneNone = true; + } + else + { + findNoneNone = false; + } + + if (string.IsNullOrEmpty(primaryEntity) && string.IsNullOrEmpty(secondaryEntity)) + { + // Get all the MessageEntities and add 'none', 'none' + + foreach (CrmMessageEntity msg in m_filterList.Values) + { + if (!hasNoneNone && msg.PrimaryEntity == "none" && msg.SecondaryEntity == "none") + { + hasNoneNone = true; + } + + msgList.Add(msg); + } + } + else + { + if (!string.IsNullOrEmpty(primaryEntity)) + { + primaryEntity = primaryEntity.Trim(); + } + if (!string.IsNullOrEmpty(secondaryEntity)) + { + secondaryEntity = secondaryEntity.Trim(); + } + + foreach (CrmMessageEntity msg in m_filterList.Values) + { + if (!string.IsNullOrEmpty(primaryEntity) && !primaryEntity.Equals(msg.PrimaryEntity, StringComparison.InvariantCultureIgnoreCase)) + { + continue; + } + + if (!string.IsNullOrEmpty(secondaryEntity) && !secondaryEntity.Equals(msg.SecondaryEntity, StringComparison.InvariantCultureIgnoreCase)) + { + continue; + } + + if (!hasNoneNone && msg.PrimaryEntity == "none" && msg.SecondaryEntity == "none") + { + hasNoneNone = true; + } + + msgList.Add(msg); + + if (stopAtFirstMatch) + { + break; + } + } + + //If we are not looking specifically for none, we don't want to add it. + if (!findNoneNone) + { + hasNoneNone = true; + } + } + + if (!hasNoneNone) + { + msgList.Add(new CrmMessageEntity(Organization, MessageId, Guid.Empty, "none", "none", + CrmPluginStepDeployment.Both, null, null)); + } + + return msgList; + } + + #endregion Private Methods + } + + public sealed class ImageMessagePropertyName + { + #region Private Fields + + private string _description; + private string _label; + private string _name; + + #endregion Private Fields + + #region Public Constructors + + public ImageMessagePropertyName(string name, string label) + : this(name, label, null) + { + } + + public ImageMessagePropertyName(string name, string label, string description) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + else if (string.IsNullOrEmpty(label)) + { + throw new ArgumentNullException("label"); + } + + _name = name; + _label = label; + _description = description; + } + + #endregion Public Constructors + + #region Public Properties + + public string Description + { + get + { + return _description; + } + } + + public string Label + { + get + { + return _label; + } + } + + public string Name + { + get + { + return _name; + } + } + + #endregion Public Properties + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmMessageEntity.cs b/Ofscrm.PluginRegistration/Wrappers/CrmMessageEntity.cs new file mode 100644 index 0000000..a3765f7 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmMessageEntity.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public sealed class CrmMessageEntity : ICrmEntity + { + #region Private Fields + + private static CrmEntityColumn[] m_entityColumns = null; + private CrmOrganization m_org; + + #endregion Private Fields + + #region Public Constructors + + public CrmMessageEntity(CrmOrganization org, Guid messageId, Guid messageEntityId, + string primaryEntity, string secondaryEntity, CrmPluginStepDeployment availability, DateTime? createdOn, DateTime? modifiedOn) + : this(org) + { + MessageEntityId = messageEntityId; + MessageId = messageId; + PrimaryEntity = primaryEntity; + SecondaryEntity = secondaryEntity; + CreatedOn = createdOn; + ModifiedOn = modifiedOn; + Availability = availability; + } + + public CrmMessageEntity(CrmOrganization org, SdkMessageFilter filter) + : this(org) + { + RefreshFromSdkMessageFilter(filter); + } + + #endregion Public Constructors + + #region Private Constructors + + private CrmMessageEntity(CrmOrganization org) + { + m_org = org; + } + + #endregion Private Constructors + + #region Public Properties + + [XmlIgnore, Browsable(false)] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Id", null, typeof(Guid)), + new CrmEntityColumn("PrimaryEntity", "Primary Entity", typeof(string)), + new CrmEntityColumn("SecondaryEntity", "Secondary Entity", typeof(string)) }; + } + + return m_entityColumns; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginStepDeployment Availability { get; set; } + + /// + /// Retrieves the Created On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn { get; private set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int CustomizationLevel { get; set; } + + [XmlIgnore, Browsable(false)] + public Guid EntityId + { + get + { + return MessageEntityId; + } + } + + [XmlIgnore, Browsable(false)] + public string EntityType + { + get + { + return SdkMessageFilter.EntityLogicalName; + } + } + + [XmlIgnore, Browsable(false)] + public bool IsSystemCrmEntity + { + get + { + return (CustomizationLevel == 0); + } + } + + [Category("Information"), Browsable(true), Description("Unique identifier of Message Filter"), ReadOnly(true)] + public Guid MessageEntityId { get; set; } + + [Category("Information"), Browsable(true), Description("Unique identifier of the Message"), ReadOnly(true)] + public Guid MessageId { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn { get; private set; } + + [Browsable(false)] + public CrmOrganization Organization + { + get + { + return m_org; + } + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + else if (m_org == null) + { + m_org = value; + } + else + { + throw new NotSupportedException("Cannot change the Organization once it has been set"); + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string PrimaryEntity { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string SecondaryEntity { get; set; } + + [XmlIgnore, Browsable(false)] + public Dictionary Values + { + get + { + Dictionary valueList = new Dictionary(); + valueList.Add("Id", MessageEntityId); + valueList.Add("PrimaryEntity", ConvertNullStringToEmpty(PrimaryEntity)); + valueList.Add("SecondaryEntity", ConvertNullStringToEmpty(SecondaryEntity)); + + return valueList; + } + } + + #endregion Public Properties + + #region Public Methods + + public Dictionary GenerateCrmEntities() + { + Dictionary entityList = new Dictionary(); + + SdkMessageFilter entity = new SdkMessageFilter(); + entity["sdkmessagefilterid"] = MessageEntityId; + entity.SdkMessageId = new EntityReference(SdkMessage.EntityLogicalName, MessageId); + entity["primaryobjecttypecode"] = PrimaryEntity; + entity["secondaryobjecttypecode"] = SecondaryEntity; + + entityList.Add(SdkMessageFilter.EntityLogicalName, entity); + + return entityList; + } + + public void RefreshFromSdkMessageFilter(SdkMessageFilter filter) + { + if (filter == null) + { + throw new ArgumentNullException("filter"); + } + + if (filter.SdkMessageFilterId != null) + { + MessageEntityId = filter.SdkMessageFilterId.Value; + } + + if (filter.SdkMessageId != null) + { + MessageId = filter.SdkMessageId.Id; + } + + if (!string.IsNullOrEmpty(filter.PrimaryObjectTypeCode)) + { + PrimaryEntity = filter.PrimaryObjectTypeCode; + } + + if (!string.IsNullOrEmpty(filter.SecondaryObjectTypeCode)) + { + SecondaryEntity = filter.SecondaryObjectTypeCode; + } + + if (filter.CustomizationLevel != null) + { + CustomizationLevel = filter.CustomizationLevel.Value; + } + + if ((string.IsNullOrWhiteSpace(PrimaryEntity) || PrimaryEntity.Equals("none")) && + (string.IsNullOrWhiteSpace(SecondaryEntity) || SecondaryEntity.Equals("none"))) + { + Availability = CrmPluginStepDeployment.Both; + } + else + { + Availability = (CrmPluginStepDeployment)Enum.ToObject(typeof(CrmPluginStepDeployment), + filter.Availability.GetValueOrDefault()); + } + + CreatedOn = filter.CreatedOn; + ModifiedOn = filter.ModifiedOn; + } + + public override string ToString() + { + return string.Format(System.Globalization.CultureInfo.InvariantCulture, "(Entity) {0}", PrimaryEntity); + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + CreatedOn = createdOn; + } + + if (modifiedOn != null) + { + ModifiedOn = modifiedOn; + } + } + + #endregion Public Methods + + #region Private Methods + + private string ConvertNullStringToEmpty(string val) + { + if (string.IsNullOrEmpty(val)) + { + return string.Empty; + } + else + { + return val; + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmOrganization.cs b/Ofscrm.PluginRegistration/Wrappers/CrmOrganization.cs new file mode 100644 index 0000000..36d283e --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmOrganization.cs @@ -0,0 +1,1247 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using McTools.Xrm.Connection; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Helpers; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public interface ICrmEntity + { + #region Public Properties + + Guid EntityId { get; } + string EntityType { get; } + bool IsSystemCrmEntity { get; } + Dictionary Values { get; } + + #endregion Public Properties + + #region Public Methods + + Dictionary GenerateCrmEntities(); + + void UpdateDates(DateTime? createdOn, DateTime? modifiedOn); + + #endregion Public Methods + } + + public interface IWcfAuthenticationHeader + { + #region Public Properties + + Guid CallerId { get; set; } + string CrmTicket { get; set; } + string OrganizationName { get; } + + #endregion Public Properties + } + + public class CrmEntityColumn + { + #region Private Fields + + private string m_label; + private string m_name; + private Type m_type; + + #endregion Private Fields + + #region Public Constructors + + public CrmEntityColumn(string name, string label, Type type) + { + if (name == null) + { + throw new ArgumentNullException("name"); + } + + m_name = name; + m_label = label; + m_type = type; + } + + #endregion Public Constructors + + #region Public Properties + + public string Label + { + get + { + return m_label; + } + } + + public string Name + { + get + { + return m_name; + } + } + + public Type Type + { + get + { + return m_type; + } + } + + #endregion Public Properties + + #region Public Methods + + public override string ToString() + { + return Name; + } + + #endregion Public Methods + } + + public sealed class CrmOrganization + { + #region Private Fields + + private Dictionary m_assemblyList = new Dictionary(); + private CrmEntityDictionary m_assemblyReadOnlyList = null; + private Exception m_attributeException = null; + private Dictionary m_attributeList = new Dictionary(); + private bool m_connected = false; + private CrmUser m_currentUser = null; + private string m_friendlyName = null; + private Dictionary m_imageList = new Dictionary(); + private CrmEntityDictionary m_imageReadOnlyList = null; + private Dictionary m_invalidEntityList = new Dictionary(); + private CrmEntityDictionary m_invalidEntityReadOnlyList = null; + private Dictionary m_messageEntityList = new Dictionary(); + private CrmEntityDictionary m_messageEntityReadOnlyList = null; + private Dictionary m_messageList = new Dictionary(); + private CrmEntityDictionary m_messageReadOnlyList = null; + private Guid m_organizationId = Guid.Empty; + private volatile IOrganizationService m_organizationService = null; + private string m_organizationServiceUrl = null; + private Dictionary m_pluginList = new Dictionary(); + private CrmEntityDictionary m_pluginReadOnlyList = null; + private Version m_serverBuild = null; + private Dictionary m_serviceEndpointList = new Dictionary(); + private CrmEntityDictionary m_serviceEndpointReadOnlyList = null; + private Dictionary m_stepList = new Dictionary(); + private CrmEntityDictionary m_stepReadOnlyList = null; + private string m_uniqueName = null; + private Dictionary m_userList = new Dictionary(); + + #endregion Private Fields + + #region Public Constructors + + public CrmOrganization(ConnectionDetail detail, OrganizationConnectionOptions connectionOptions) + { + if (detail == null) + { + throw new ArgumentNullException("detail"); + } + + OrganizationServiceUrl = detail.OrganizationServiceUrl; + WebApplicationUrl = detail.WebApplicationUrl; + + OrganizationFriendlyName = detail.OrganizationFriendlyName; + OrganizationUniqueName = detail.Organization; + ServerBuild = new Version(detail.OrganizationVersion); + + ConnectionDetail = detail; + + OrganizationHelper.OpenConnection(this, OrganizationHelper.RetrieveMessages(this), connectionOptions); + } + + #endregion Public Constructors + + #region Public Properties + + [XmlIgnore] + public CrmEntityDictionary Assemblies + { + get + { + if (m_assemblyReadOnlyList == null) + { + m_assemblyReadOnlyList = new CrmEntityDictionary(m_assemblyList); + } + + return m_assemblyReadOnlyList; + } + } + + [XmlIgnore] + public Exception AttributeLoadException + { + get + { + return m_attributeException; + } + } + + [XmlIgnore] + public bool Connected + { + get + { + return m_connected; + } + set + { + if (!value) + { + //Reset when closing the connection + SecureConfigurationPermissionDenied = false; + m_currentUser = null; + m_invalidEntityList.Clear(); + ProfilerPlugin = null; + } + + m_connected = value; + } + } + + public ConnectionDetail ConnectionDetail { get; set; } + + [XmlIgnore] + public CrmEntityDictionary Images + { + get + { + if (m_imageReadOnlyList == null) + { + m_imageReadOnlyList = new CrmEntityDictionary(m_imageList); + } + + return m_imageReadOnlyList; + } + } + + [XmlIgnore] + public CrmEntityDictionary InvalidEntities + { + get + { + if (m_invalidEntityReadOnlyList == null) + { + m_invalidEntityReadOnlyList = new CrmEntityDictionary(m_invalidEntityList); + } + + return m_invalidEntityReadOnlyList; + } + } + + [XmlIgnore] + public CrmUser LoggedOnUser + { + get + { + return m_currentUser; + } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + else + { + m_currentUser = value; + } + } + } + + [XmlIgnore] + public CrmEntityDictionary MessageEntities + { + get + { + if (m_messageEntityReadOnlyList == null) + { + m_messageEntityReadOnlyList = new CrmEntityDictionary(m_messageEntityList); + } + + return m_messageEntityReadOnlyList; + } + } + + [XmlIgnore] + public CrmEntityDictionary Messages + { + get + { + if (m_messageReadOnlyList == null) + { + m_messageReadOnlyList = new CrmEntityDictionary(m_messageList); + } + + return m_messageReadOnlyList; + } + } + + [XmlElement(ElementName = "OrganizationFriendlyName", Type = typeof(string), IsNullable = false)] + public string OrganizationFriendlyName + { + get + { + return m_friendlyName; + } + set + { + m_friendlyName = value; + } + } + + [XmlElement(ElementName = "OrganizationId", IsNullable = false)] + public Guid OrganizationId + { + get + { + return m_organizationId; + } + set + { + m_organizationId = value; + } + } + + [XmlElement(ElementName = "CrmServiceUrl", Type = typeof(string), IsNullable = false)] + public string OrganizationServiceUrl + { + get + { + return m_organizationServiceUrl; + } + set + { + m_organizationServiceUrl = value; + m_organizationService = null; + m_connected = false; + } + } + + [XmlElement(ElementName = "OrganizationUniqueName", Type = typeof(string), IsNullable = false)] + public string OrganizationUniqueName + { + get + { + return m_uniqueName; + } + set + { + m_uniqueName = value; + } + } + + [XmlIgnore] + public CrmEntityDictionary Plugins + { + get + { + if (m_pluginReadOnlyList == null) + { + m_pluginReadOnlyList = new CrmEntityDictionary(m_pluginList); + } + + return m_pluginReadOnlyList; + } + } + + [XmlIgnore] + public CrmPlugin ProfilerPlugin { get; set; } + + [XmlIgnore] + public bool SecureConfigurationPermissionDenied { get; set; } + + [XmlIgnore] + public Version ServerBuild + { + get + { + return m_serverBuild; + } + + set + { + if (null == value) + { + throw new ArgumentNullException("value"); + } + else + { + m_serverBuild = value; + } + } + } + + [XmlIgnore] + public CrmEntityDictionary ServiceEndpoints + { + get + { + if (m_serviceEndpointReadOnlyList == null) + { + m_serviceEndpointReadOnlyList = new CrmEntityDictionary(m_serviceEndpointList); + } + + return m_serviceEndpointReadOnlyList; + } + } + + [XmlIgnore] + public CrmEntityDictionary Steps + { + get + { + if (m_stepReadOnlyList == null) + { + m_stepReadOnlyList = new CrmEntityDictionary(m_stepList); + } + + return m_stepReadOnlyList; + } + } + + [XmlIgnore] + public Dictionary Users + { + get + { + return m_userList; + } + } + + [XmlIgnore] + public string WebApplicationUrl { get; set; } + + #endregion Public Properties + + #region Internal Properties + + [XmlIgnore] + internal IOrganizationService OrganizationService + { + get + { + lock (this) + { + if (null == m_organizationService) + { + InitializeOrganizationService(); + } + + return m_organizationService; + } + } + } + + #endregion Internal Properties + + #region Public Indexers + + [XmlIgnore] + public CrmPluginAssembly this[Guid assemblyId] + { + get + { + if (Assemblies != null) + { + return Assemblies[assemblyId]; + } + else + { + return null; + } + } + } + + #endregion Public Indexers + + #region Public Methods + + public void AddAssembly(CrmPluginAssembly assembly) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + else if (m_assemblyList.ContainsKey(assembly.AssemblyId)) + { + throw new ArgumentException("Assembly is already in the list"); + } + else + { + ValidateEntity(assembly); + } + + m_assemblyList.Add(assembly.AssemblyId, assembly); + } + + public void AddImage(CrmPluginStep step, CrmPluginImage image) + { + if (image == null) + { + throw new ArgumentNullException("image"); + } + else if (step == null) + { + throw new ArgumentNullException("step"); + } + else if (!step.Images.ContainsKey(image.ImageId)) + { + step.AddImage(image); + return; + } + else + { + ValidateEntity(image); + } + + m_imageList.Add(image.ImageId, image); + } + + public void AddMessage(CrmMessage message) + { + if (message == null) + { + throw new ArgumentNullException("message"); + } + else if (m_messageList.ContainsKey(message.MessageId)) + { + throw new ArgumentException("Message is already in the list"); + } + else + { + ValidateEntity(message); + } + + m_messageList.Add(message.MessageId, message); + } + + public void AddMessageEntity(CrmMessage message, CrmMessageEntity entity) + { + if (message == null) + { + throw new ArgumentNullException("message"); + } + else if (entity == null) + { + throw new ArgumentNullException("entity"); + } + else if (!message.MessageEntities.ContainsKey(entity.MessageEntityId)) + { + message.AddMessageEntity(entity); + return; + } + else + { + ValidateEntity(entity); + } + + m_messageEntityList.Add(entity.EntityId, entity); + } + + public void AddPlugin(CrmPluginAssembly assembly, CrmPlugin plugin) + { + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + else if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + else if (!assembly.Plugins.ContainsKey(plugin.PluginId)) + { + assembly.AddPlugin(plugin); + return; + } + else + { + ValidateEntity(plugin); + } + + m_pluginList.Add(plugin.PluginId, plugin); + } + + public void AddServiceEndpoint(CrmServiceEndpoint serviceEndpoint) + { + if (serviceEndpoint == null) + { + throw new ArgumentNullException("serviceEndpoint"); + } + if (m_serviceEndpointList.ContainsKey(serviceEndpoint.ServiceEndpointId)) + { + throw new ArgumentException("ServiceEndpoint is already in the list"); + } + + m_serviceEndpointList.Add(serviceEndpoint.ServiceEndpointId, serviceEndpoint); + } + + public void AddStep(CrmPlugin plugin, CrmPluginStep step) + { + if (step == null) + { + throw new ArgumentNullException("step"); + } + else if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + else if (!plugin.Steps.ContainsKey(step.StepId)) + { + plugin.AddStep(step); + return; + } + else + { + ValidateEntity(step); + } + + m_stepList.Add(step.StepId, step); + } + + /// + /// Clears all saved entity attributes + /// + public void ClearAllEntityAttributes() + { + m_attributeList.Clear(); + m_attributeException = null; + } + + public void ClearAssemblies() + { + m_imageList.Clear(); + m_stepList.Clear(); + m_pluginList.Clear(); + m_assemblyList.Clear(); + } + + public void ClearImages() + { + ClearImages(Guid.Empty); + } + + public void ClearImages(Guid stepId) + { + CrmPluginImage[] imageList; + if (stepId == Guid.Empty) + { + //Copy the list of images. Can't use the enumerator because we are changing the underlying data + imageList = new CrmPluginImage[m_imageList.Count]; + m_imageList.Values.CopyTo(imageList, 0); + } + else if (m_stepList.ContainsKey(stepId)) + { + //Copy the list of images. Can't use the enumerator because we are changing the underlying data + imageList = m_stepList[stepId].Images.ToArray(); + } + else + { + throw new ArgumentException("Invalid Entity Id", "stepId"); + } + + //Loop through the image id's + foreach (CrmPluginImage image in imageList) + { + RemoveImage(image.StepId, image.ImageId); + } + } + + public void ClearMessageEntities() + { + ClearMessageEntities(Guid.Empty); + } + + public void ClearMessageEntities(Guid messageId) + { + CrmMessageEntity[] entityList; + if (messageId == Guid.Empty) + { + //Copy the list of entities. Can't use the enumerator because we are changing the underlying data + entityList = new CrmMessageEntity[m_messageEntityList.Count]; + m_messageEntityList.Values.CopyTo(entityList, 0); + } + else if (m_messageList.ContainsKey(messageId)) + { + //Copy the list of entities. Can't use the enumerator because we are changing the underlying data + entityList = m_messageList[messageId].MessageEntities.ToArray(); + } + else + { + throw new ArgumentException("Invalid Entity Id", "messageId"); + } + + //Loop through the entity id's + foreach (CrmMessageEntity message in entityList) + { + RemoveMessageEntity(message.MessageId, message.MessageEntityId); + } + } + + public void ClearMessages() + { + m_messageEntityList.Clear(); + m_messageList.Clear(); + } + + public void ClearPlugins() + { + ClearPlugins(Guid.Empty); + } + + public void ClearPlugins(Guid assemblyId) + { + CrmPlugin[] pluginList; + if (assemblyId == Guid.Empty) + { + m_imageList.Clear(); + m_stepList.Clear(); + + //Copy the list of plugins. Can't use the enumerator because we are changing the underlying data + pluginList = new CrmPlugin[m_pluginList.Count]; + m_pluginList.Values.CopyTo(pluginList, 0); + } + else if (m_assemblyList.ContainsKey(assemblyId)) + { + //Copy the list of plugins. Can't use the enumerator because we are changing the underlying data + pluginList = m_assemblyList[assemblyId].Plugins.ToArray(); + } + else + { + throw new ArgumentException("Invalid Entity Id", "assemblyId"); + } + + //Loop through the plugin id's + foreach (CrmPlugin plugin in pluginList) + { + RemovePlugin(plugin.AssemblyId, plugin.PluginId); + } + } + + public void ClearServiceEndpoints() + { + m_serviceEndpointList.Clear(); + } + + public void ClearSteps() + { + ClearSteps(Guid.Empty); + } + + public void ClearSteps(Guid pluginId) + { + CrmPluginStep[] stepList; + if (pluginId == Guid.Empty) + { + m_imageList.Clear(); + + //Copy the list of steps. Can't use the enumerator because we are changing the underlying data + stepList = new CrmPluginStep[m_stepList.Count]; + m_stepList.Values.CopyTo(stepList, 0); + } + else if (m_pluginList.ContainsKey(pluginId)) + { + //Copy the list of steps. Can't use the enumerator because we are changing the underlying data + stepList = m_pluginList[pluginId].Steps.ToArray(); + } + else + { + throw new ArgumentException("Invalid Entity Id", "pluginId"); + } + + //Loop through the step id's + foreach (CrmPluginStep step in stepList) + { + RemoveStep(step.PluginId, step.StepId); + } + } + + /// + /// Locate the message based on the name of the message + /// + /// Message to be found + /// CrmMessage if found, null if not + public CrmMessage FindMessage(string messageName) + { + if (messageName == null) + { + throw new ArgumentNullException("message"); + } + + foreach (CrmMessage msg in m_messageList.Values) + { + if (messageName.Equals(msg.Name, StringComparison.InvariantCultureIgnoreCase)) + { + return msg; + } + } + + return null; + } + + /// + /// Method that initializes needed variables. This can be done in a thread + /// + public void Initialize() + { + lock (this) + { + if (m_organizationService == null) + { + InitializeOrganizationService(); + } + } + } + + /// + /// Determines if the attributes for a specific entity have been loaded + /// + public bool IsEntityAttributesLoaded(string entityName) + { + return m_attributeList.ContainsKey(entityName); + } + + public void RemoveAssembly(Guid assemblyId) + { + if (m_assemblyList.ContainsKey(assemblyId)) + { + CrmPluginAssembly assembly = m_assemblyList[assemblyId]; + + //Copy the list of plugins. Can't use the enumerator because we are changing the underlying data + Guid[] pluginIdList = new Guid[assembly.Plugins.Count]; + assembly.Plugins.Keys.CopyTo(pluginIdList, 0); + + //Loop through the plugin id's + foreach (Guid pluginId in pluginIdList) + { + RemovePlugin(assembly, pluginId); + } + + m_assemblyList.Remove(assemblyId); + } + else + { + throw new ArgumentException("Invalid Assembly Id", "assemblyId"); + } + } + + public void RemoveImage(Guid stepId, Guid imageId) + { + if (m_stepList.ContainsKey(stepId)) + { + RemoveImage(m_stepList[stepId], imageId); + } + else + { + throw new ArgumentException("Invalid Entity Id", "stepId"); + } + } + + public void RemoveImage(CrmPluginStep step, Guid imageId) + { + if (step == null) + { + throw new ArgumentNullException("plugin"); + } + else if (step.Images.ContainsKey(imageId)) + { + step.RemoveImage(imageId); + } + else if (m_imageList.ContainsKey(imageId)) + { + m_imageList.Remove(imageId); + } + else + { + throw new ArgumentException("Image is not in list", "step"); + } + } + + public void RemoveMessage(Guid messageId) + { + if (m_messageList.ContainsKey(messageId)) + { + CrmMessage message = m_messageList[messageId]; + + //Copy the list of MessageEntities. Can't use the enumerator because we are changing the underlying data + Guid[] entityIdList = new Guid[message.MessageEntities.Count]; + message.MessageEntities.Keys.CopyTo(entityIdList, 0); + + //Loop through the MessageEntity id's + foreach (Guid messageEntityId in entityIdList) + { + RemoveMessageEntity(message, messageEntityId); + } + + m_messageList.Remove(messageId); + } + else + { + throw new ArgumentException("Invalid Message Id", "messageId"); + } + } + + public void RemoveMessageEntity(Guid messageId, Guid messageEntityId) + { + if (m_messageList.ContainsKey(messageId)) + { + RemoveMessageEntity(m_messageList[messageId], messageEntityId); + } + else + { + throw new ArgumentException("Invalid Entity Id", "messageId"); + } + } + + public void RemoveMessageEntity(CrmMessage message, Guid messageEntityId) + { + if (message == null) + { + throw new ArgumentNullException("message"); + } + else if (message.MessageEntities.ContainsKey(messageEntityId)) + { + message.RemoveMessageEntity(messageEntityId); + } + else if (m_messageEntityList.ContainsKey(messageEntityId)) + { + m_messageEntityList.Remove(messageEntityId); + } + else + { + throw new ArgumentException("MessageEntity is not in list", "messageEntityId"); + } + } + + public void RemovePlugin(Guid assemblyId, Guid pluginId) + { + if (m_assemblyList.ContainsKey(assemblyId)) + { + RemovePlugin(m_assemblyList[assemblyId], pluginId); + } + else + { + throw new ArgumentException("Invalid Entity Id", "assemblyId"); + } + } + + public void RemovePlugin(CrmPluginAssembly assembly, Guid pluginId) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + else if (assembly.Plugins.ContainsKey(pluginId)) + { + assembly.RemovePlugin(pluginId); + } + else if (m_pluginList.ContainsKey(pluginId)) + { + CrmPlugin plugin = m_pluginList[pluginId]; + + //Copy the list of steps. Can't use the enumerator because we are changing the underlying data + Guid[] stepIdList = new Guid[plugin.Steps.Count]; + plugin.Steps.Keys.CopyTo(stepIdList, 0); + + //Loop through the step id's + foreach (Guid stepId in stepIdList) + { + RemoveStep(plugin, stepId); + } + + m_pluginList.Remove(pluginId); + } + else + { + throw new ArgumentException("Plugin is not in list", "pluginId"); + } + } + + public void RemoveServiceEndpoint(Guid serviceEndpointId) + { + if (m_serviceEndpointList.ContainsKey(serviceEndpointId)) + { + m_serviceEndpointList.Remove(serviceEndpointId); + } + else + { + throw new ArgumentException("Invalid ServiceEndpoint Id", "serviceEndpointId"); + } + } + + public void RemoveStep(Guid pluginId, Guid stepId) + { + if (m_pluginList.ContainsKey(pluginId)) + { + RemoveStep(m_pluginList[pluginId], stepId); + } + else + { + throw new ArgumentException("Invalid Entity Id", "pluginId"); + } + } + + public void RemoveStep(CrmPlugin plugin, Guid stepId) + { + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + else if (plugin.Steps.ContainsKey(stepId)) + { + plugin.RemoveStep(stepId); + } + else if (m_stepList.ContainsKey(stepId)) + { + CrmPluginStep step = m_stepList[stepId]; + + //Copy the list of images. Can't use the enumerator because we are changing the underlying data + Guid[] imageIdList = new Guid[step.Images.Count]; + step.Images.Keys.CopyTo(imageIdList, 0); + + //Loop through the image id's + foreach (Guid imageId in imageIdList) + { + RemoveImage(step, imageId); + } + + m_stepList.Remove(stepId); + } + else + { + throw new ArgumentException("Step is not in list", "stepId"); + } + } + + /// + /// Retrieves the entity attributes for the specified entity + /// + public CrmAttribute[] RetrieveEntityAttributes(string entityName) + { + if (m_attributeList.ContainsKey(entityName)) + { + return m_attributeList[entityName]; + } + else + { + throw new ArgumentException("Entity is not loaded", "entityName"); + } + } + + public void SaveEntityAttributes(string entityName, Exception loadException) + { + if (loadException == null) + { + throw new ArgumentNullException("loadException"); + } + else if (entityName == null) + { + throw new ArgumentNullException("entityName"); + } + else if (m_attributeList.ContainsKey(entityName)) + { + m_attributeList.Remove(entityName); + } + + m_attributeException = loadException; + } + + /// + /// Save a specific list of attributes for a specific entity + /// + public void SaveEntityAttributes(string entityName, CrmAttribute[] attributes) + { + if (entityName == null) + { + throw new ArgumentNullException("entityName"); + } + else if (attributes == null) + { + throw new ArgumentNullException("attributes"); + } + + if (m_attributeList.ContainsKey(entityName)) + { + m_attributeList[entityName] = attributes; + } + else + { + m_attributeList.Add(entityName, attributes); + } + + m_attributeException = null; + } + + #endregion Public Methods + + #region Private Methods + + /// + /// Initialize the CrmService + /// + private void InitializeOrganizationService() + { + lock (this) + { + m_organizationService = ConnectionDetail.GetCrmServiceClient().OrganizationServiceProxy; + } + } + + private void ValidateEntity(CrmPluginAssembly assembly) + { + if (assembly == null) + { + throw new ArgumentNullException(); + } + else if (m_assemblyList.ContainsKey(assembly.AssemblyId)) + { + throw new ArgumentException("Assembly is already in the list"); + } + else if (assembly.Organization != this) + { + throw new ArgumentException("Organization must match"); + } + else if (assembly.AssemblyId == Guid.Empty) + { + throw new ArgumentException("AssemblyId must be set to valid Guid"); + } + } + + private void ValidateEntity(CrmPlugin plugin) + { + if (plugin == null) + { + throw new ArgumentNullException(); + } + else if (m_pluginList.ContainsKey(plugin.PluginId)) + { + throw new ArgumentException("Plugin is already in the list"); + } + else if (plugin.Organization != this) + { + throw new ArgumentException("Organization must match"); + } + else if (plugin.AssemblyId == Guid.Empty) + { + throw new ArgumentException("AssemblyId must be set to valid Guid"); + } + else if (plugin.PluginId == Guid.Empty) + { + throw new ArgumentException("PluginId must be set to valid Guid"); + } + } + + private void ValidateEntity(CrmPluginStep step) + { + if (step == null) + { + throw new ArgumentNullException(); + } + else if (m_stepList.ContainsKey(step.StepId)) + { + throw new ArgumentException("Step is already in the list"); + } + else if (step.Organization != this) + { + throw new ArgumentException("Organization must match"); + } + else if (step.AssemblyId == Guid.Empty) + { + throw new ArgumentException("AssemblyId must be set to valid Guid"); + } + else if (step.PluginId == Guid.Empty) + { + throw new ArgumentException("PluginId must be set to valid Guid"); + } + else if (step.StepId == Guid.Empty) + { + throw new ArgumentException("StepId must be set to valid Guid"); + } + } + + private void ValidateEntity(CrmPluginImage image) + { + if (image == null) + { + throw new ArgumentNullException(); + } + else if (m_imageList.ContainsKey(image.ImageId)) + { + throw new ArgumentException("Image is already in the list"); + } + else if (image.Organization != this) + { + throw new ArgumentException("Organization must match"); + } + else if (image.AssemblyId == Guid.Empty) + { + throw new ArgumentException("AssemblyId must be set to valid Guid"); + } + else if (image.PluginId == Guid.Empty) + { + throw new ArgumentException("PluginId must be set to valid Guid"); + } + else if (image.StepId == Guid.Empty) + { + throw new ArgumentException("StepId must be set to valid Guid"); + } + else if (image.ImageId == Guid.Empty) + { + throw new ArgumentException("ImageId must be set to valid Guid"); + } + } + + private void ValidateEntity(CrmMessage message) + { + if (message == null) + { + throw new ArgumentNullException(); + } + else if (m_messageList.ContainsKey(message.MessageId)) + { + throw new ArgumentException("Message is already in the list"); + } + else if (message.Organization != this) + { + throw new ArgumentException("Organization must match"); + } + else if (message.MessageId == Guid.Empty) + { + throw new ArgumentException("MessageId must be set to valid Guid"); + } + } + + private void ValidateEntity(CrmMessageEntity messageEntity) + { + if (messageEntity == null) + { + throw new ArgumentNullException(); + } + else if (m_messageEntityList.ContainsKey(messageEntity.MessageEntityId)) + { + throw new ArgumentException("MessageEntity is already in the list"); + } + else if (messageEntity.Organization != this) + { + throw new ArgumentException("Organization must match"); + } + else if (messageEntity.MessageId == Guid.Empty) + { + throw new ArgumentException("MessageId must be set to valid Guid"); + } + else if (messageEntity.MessageEntityId == Guid.Empty) + { + throw new ArgumentException("MessageEntityId must be set to valid Guid"); + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmPlugin.cs b/Ofscrm.PluginRegistration/Wrappers/CrmPlugin.cs new file mode 100644 index 0000000..3b5569f --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmPlugin.cs @@ -0,0 +1,746 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public enum CrmPluginIsolatable + { + Yes, + No, + Unknown + } + + public enum CrmPluginType + { + Plugin, + WorkflowActivity + } + + [Serializable] + public sealed class CrmPlugin : ICrmEntity, ICloneable + { + #region Public Fields + + public const string RelationshipTypeToStep = "plugintype_sdkmessageprocessingstep"; + + #endregion Public Fields + + #region Private Fields + + private const string V3CalloutProxyTypeName = "Microsoft.Crm.Extensibility.V3CalloutProxyPlugin"; + private static CrmEntityColumn[] m_entityColumns = null; + private string m_assemblyName = null; + private DateTime? m_createdOn = null; + private int m_customizationLevel = 1; + private string m_friendlyName; + private bool m_friendlyNameIgnore; + private CrmPluginIsolatable m_isolatable = CrmPluginIsolatable.Unknown; + private DateTime? m_modifiedOn = null; + private string m_name = null; + private CrmOrganization m_org; + private Guid m_pluginAssemblyId = Guid.Empty; + private Guid m_pluginId = Guid.Empty; + private CrmPluginType m_plugType = CrmPluginType.Plugin; + private Dictionary m_stepList = new Dictionary(); + private CrmEntityDictionary m_stepReadOnlyList = null; + private string m_typeName = null; + private string m_workflowActivityGroupName = null; + + #endregion Private Fields + + #region Public Constructors + + public CrmPlugin(CrmOrganization org) + { + m_org = org; + FriendlyName = Guid.NewGuid().ToString(); + } + + public CrmPlugin(CrmOrganization org, Guid pluginId, Guid assemblyId, string assemblyName, string friendlyName, + string typeName, CrmPluginType type, CrmPluginIsolatable isolatable, DateTime? createdOn, DateTime? modifiedOn) + : this(org) + { + PluginId = pluginId; + AssemblyId = assemblyId; + AssemblyName = assemblyName; + TypeName = typeName; + Name = typeName; + FriendlyName = friendlyName; + PluginType = type; + Isolatable = isolatable; + UpdateDates(createdOn, modifiedOn); + } + + public CrmPlugin(CrmOrganization org, PluginType type) + : this(org) + { + RefreshFromPluginType(type); + } + + #endregion Public Constructors + + #region Public Properties + + [XmlIgnore] + [Browsable(false)] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Assembly", "Assembly", typeof(string)), + new CrmEntityColumn("ModifiedOn", "Modified On", typeof(string)), + new CrmEntityColumn("FriendlyName", "Friendly Name", typeof(string)), + new CrmEntityColumn("Name", "Name", typeof(string)), + new CrmEntityColumn("TypeName", "Type Name", typeof(string)), + new CrmEntityColumn("WorkflowActivityGroupName", "WorkflowActivityGroupName", typeof(string)), + new CrmEntityColumn("Description", "Description", typeof(string)), + new CrmEntityColumn("Isolatable", "Isolatable", typeof(string)), + new CrmEntityColumn("Id", "PluginId", typeof(Guid)) }; + } + + return m_entityColumns; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid AssemblyId + { + get + { + return m_pluginAssemblyId; + } + set + { + if (value == m_pluginAssemblyId) + { + return; + } + + m_pluginAssemblyId = value; + + foreach (CrmPluginStep step in m_stepList.Values) + { + step.AssemblyId = value; + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string AssemblyName + { + get + { + return m_assemblyName; + } + + set + { + m_assemblyName = value; + } + } + + /// + /// Retrieves the Created On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn + { + get + { + return m_createdOn; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int CustomizationLevel + { + get + { + return m_customizationLevel; + } + + set + { + if (value < 0) + { + throw new ArgumentException("Invalid CustomizationLevel specified"); + } + + m_customizationLevel = value; + } + } + + [Category("Editable"), Browsable(true), ReadOnly(false)] + public string Description + { + get; + set; + } + + [XmlIgnore] + [Browsable(false)] + public Guid EntityId + { + get + { + return m_pluginId; + } + } + + [XmlIgnore] + [Browsable(false)] + public string EntityType + { + get + { + return Ofscrm.PluginRegistration.Entities.PluginType.EntityLogicalName; + } + } + + [Category("Editable"), Browsable(true), ReadOnly(false)] + public string FriendlyName + { + get + { + return m_friendlyName; + } + set + { + m_friendlyName = GenerateFriendlyName(value, out m_friendlyNameIgnore); + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginIsolatable Isolatable + { + get + { + return m_isolatable; + } + + set + { + m_isolatable = value; + } + } + + [Browsable(false)] + public bool IsProfilerPlugin { get; set; } + + [XmlIgnore] + [Category("Information"), Browsable(true), ReadOnly(true)] + public bool IsSystemCrmEntity + { + get + { + return CustomizationLevel == 0; + } + } + + /// + /// Retrieves the Modified On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn + { + get + { + return m_modifiedOn; + } + } + + [Category("Editable"), Browsable(true), ReadOnly(false)] + public string Name + { + get + { + return m_name; + } + set + { + m_name = value; + } + } + + [XmlIgnore] + [Browsable(false)] + public Guid NodeId + { + get + { + return m_pluginId; + } + } + + [XmlIgnore] + [Browsable(false)] + public string NodeText + { + get + { + if (IsProfilerPlugin) + { + return "Plug-in Profiler"; + } + + string format; + if (CrmPluginIsolatable.Yes == Isolatable) + { + format = "({0}) {2} - Isolatable"; + } + else if (string.IsNullOrWhiteSpace(WorkflowActivityGroupName) || + WorkflowActivityGroupName.StartsWith(AssemblyName + " (", StringComparison.Ordinal)) + { + format = "({0}) {2}"; + } + else + { + format = "({0}) {1}: {2}"; + } + + return string.Format(format, NodeTypeLabel, WorkflowActivityGroupName, string.IsNullOrWhiteSpace(Name) ? Description : Name); + } + } + + [XmlIgnore] + [Browsable(false)] + public string NodeTypeLabel + { + get + { + switch (PluginType) + { + case CrmPluginType.Plugin: + return "Plugin"; + + case CrmPluginType.WorkflowActivity: + return "Workflow Activity"; + + default: + throw new NotImplementedException("PluginType = " + PluginType.ToString()); + } + } + } + + [Browsable(false)] + public CrmOrganization Organization + { + get + { + return m_org; + } + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + else if (m_org == null) + { + m_org = value; + + foreach (CrmPluginStep step in m_stepList.Values) + { + if (step.Organization == null) + { + step.Organization = m_org; + } + + Organization.AddStep(this, step); + } + } + else + { + throw new NotSupportedException("Cannot change the Organization once it has been set"); + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid PluginId + { + get + { + return m_pluginId; + } + set + { + if (value == m_pluginId) + { + return; + } + + m_pluginId = value; + + foreach (CrmPluginStep step in m_stepList.Values) + { + step.PluginId = value; + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginType PluginType + { + get + { + return m_plugType; + } + set + { + m_plugType = value; + } + } + + [Browsable(false)] + public CrmEntityDictionary Steps + { + get + { + if (m_stepReadOnlyList == null) + { + m_stepReadOnlyList = new CrmEntityDictionary(m_stepList); + } + + return m_stepReadOnlyList; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string TypeName + { + get + { + return m_typeName; + } + + set + { + m_typeName = value; + } + } + + [XmlIgnore] + [Browsable(false)] + public Dictionary Values + { + get + { + Dictionary valueList = new Dictionary(); + valueList.Add("Id", PluginId); + valueList.Add("Assembly", AssemblyName); + valueList.Add("ModifiedOn", ModifiedOn); + valueList.Add("FriendlyName", FriendlyName); + valueList.Add("Name", Name); + valueList.Add("TypeName", TypeName); + valueList.Add("WorkflowActivityGroupName", WorkflowActivityGroupName); + valueList.Add("Isolatable", Isolatable.ToString()); + valueList.Add("Description", Description); + return valueList; + } + } + + [Category("Editable"), Browsable(true), ReadOnly(false)] + public string WorkflowActivityGroupName + { + get + { + return m_workflowActivityGroupName; + } + set + { + m_workflowActivityGroupName = value; + } + } + + #endregion Public Properties + + #region Public Indexers + + [Browsable(false)] + public CrmPluginStep this[Guid stepId] + { + get + { + return m_stepList[stepId]; + } + } + + #endregion Public Indexers + + #region Public Methods + + public void AddStep(CrmPluginStep step) + { + if (step == null) + { + throw new ArgumentNullException("step"); + } + + m_stepList.Add(step.StepId, step); + + if (Organization != null) + { + Organization.AddStep(this, step); + } + } + + public void ClearSteps() + { + m_stepList.Clear(); + + if (Organization != null) + { + Organization.ClearSteps(PluginId); + } + } + + public object Clone() + { + return Clone(true); + } + + public CrmPlugin Clone(bool includeOrganization) + { + CrmPlugin newPlugin; + if (includeOrganization) + { + newPlugin = new CrmPlugin(m_org); + } + else + { + newPlugin = new CrmPlugin(null); + } + + newPlugin.m_assemblyName = m_assemblyName; + newPlugin.m_createdOn = m_createdOn; + newPlugin.m_customizationLevel = m_customizationLevel; + newPlugin.m_friendlyName = m_friendlyName; + newPlugin.m_friendlyNameIgnore = m_friendlyNameIgnore; + newPlugin.m_isolatable = m_isolatable; + newPlugin.m_modifiedOn = m_modifiedOn; + newPlugin.m_pluginAssemblyId = m_pluginAssemblyId; + newPlugin.m_pluginId = m_pluginId; + newPlugin.m_plugType = m_plugType; + newPlugin.m_typeName = m_typeName; + + //Create a new step list + Dictionary newStepList = new Dictionary(); + foreach (CrmPluginStep step in m_stepList.Values) + { + //Clone the step + CrmPluginStep clonedStep = (CrmPluginStep)step.Clone(includeOrganization); + + //Add the step to the new list + newStepList.Add(clonedStep.StepId, clonedStep); + } + + //Assign the list to the new object + newPlugin.m_stepList = newStepList; + + return newPlugin; + } + + public Dictionary GenerateCrmEntities() + { + PluginType plugin = new PluginType(); + if (PluginId != Guid.Empty) + { + plugin["plugintypeid"] = new Guid?(); + plugin["plugintypeid"] = PluginId; + } + + if (AssemblyId != Guid.Empty) + { + plugin.PluginAssemblyId = new EntityReference(); + plugin.PluginAssemblyId.LogicalName = PluginAssembly.EntityLogicalName; + plugin.PluginAssemblyId.Id = AssemblyId; + } + else + { + throw new ArgumentException("PluginAssembly has not been set", "plugin"); + } + + plugin.TypeName = TypeName; + plugin.FriendlyName = m_friendlyName; + + plugin.Name = Name; + plugin.Description = Description; + plugin.WorkflowActivityGroupName = WorkflowActivityGroupName; + + Dictionary entityList = new Dictionary(); + entityList.Add(Ofscrm.PluginRegistration.Entities.PluginType.EntityLogicalName, plugin); + + return entityList; + } + + public string GenerateNodeText(string newFriendlyName) + { + bool ignoreFriendlyName; + string newText = GenerateFriendlyName(newFriendlyName, out ignoreFriendlyName); + + if (ignoreFriendlyName) + { + return TypeName; + } + else + { + return newText; + } + } + + public void RefreshFromPluginType(PluginType type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + if (type.AssemblyName != null) + { + AssemblyName = type.AssemblyName; + } + + if (type.TypeName != null) + { + TypeName = type.TypeName; + } + + if (type.FriendlyName != null) + { + FriendlyName = type.FriendlyName; + } + + if (type.Name != null) + { + Name = type.Name; + } + + Description = type.Description; + + if (type.PluginTypeId != null) + { + PluginId = type.PluginTypeId.Value; + } + + if (type.PluginAssemblyId != null) + { + AssemblyId = type.PluginAssemblyId.Id; + } + + if (type.CustomizationLevel != null) + { + CustomizationLevel = type.CustomizationLevel.Value; + } + + if (type.CreatedOn != null && (type.CreatedOn.HasValue)) + { + m_createdOn = type.CreatedOn.Value; + } + + if (type.ModifiedOn != null && (type.ModifiedOn.HasValue)) + { + m_modifiedOn = type.ModifiedOn.Value; + } + + if (type.IsWorkflowActivity != null && (type.IsWorkflowActivity.HasValue)) + { + if (type.IsWorkflowActivity.Value) + { + PluginType = CrmPluginType.WorkflowActivity; + } + else + { + PluginType = CrmPluginType.Plugin; + } + } + + WorkflowActivityGroupName = type.WorkflowActivityGroupName; + } + + public void RemoveStep(Guid stepId) + { + if (m_stepList.ContainsKey(stepId)) + { + m_stepList.Remove(stepId); + + if (Organization != null) + { + Organization.RemoveStep(this, stepId); + } + } + else + { + throw new ArgumentException("Invalid Step Id", "stepId"); + } + } + + public override string ToString() + { + return NodeText; + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + m_createdOn = createdOn; + } + + if (modifiedOn != null) + { + m_modifiedOn = modifiedOn; + } + } + + #endregion Public Methods + + #region Private Methods + + private string ConvertNullStringToEmpty(string val) + { + if (string.IsNullOrEmpty(val)) + { + return string.Empty; + } + else + { + return val; + } + } + + private string GenerateFriendlyName(string newName, out bool ignoreFriendlyName) + { + if (string.IsNullOrEmpty(newName) || + string.Equals(m_typeName, newName, StringComparison.InvariantCultureIgnoreCase)) + { + ignoreFriendlyName = true; + if (m_friendlyNameIgnore) + { + return m_friendlyName; + } + else + { + return Guid.NewGuid().ToString(); + } + } + else + { + // Checking if name should be ignored + var guidOutput = Guid.Empty; + ignoreFriendlyName = Guid.TryParse(newName, out guidOutput); + + return newName; + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmPluginAssembly.cs b/Ofscrm.PluginRegistration/Wrappers/CrmPluginAssembly.cs new file mode 100644 index 0000000..c5fc877 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmPluginAssembly.cs @@ -0,0 +1,602 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public enum CrmAssemblyIsolationMode + { + None = 1, + Sandbox = 2 + } + + public enum CrmAssemblySourceType + { + Database = 0, + Disk = 1, + GAC = 2 + } + + [Serializable] + public sealed class CrmPluginAssembly : ICrmEntity, ICloneable + { + #region Public Fields + + public const string RelationshipAssemblyToType = "pluginassembly_plugintype"; + + #endregion Public Fields + + #region Private Fields + + private static CrmEntityColumn[] m_entityColumns = null; + private Guid m_assemblyId = Guid.Empty; + private int m_customizationLevel; + private string m_Name = null; + private CrmOrganization m_org = null; + private Dictionary m_pluginList = new Dictionary(); + private CrmEntityDictionary m_pluginReadOnlyList = null; + + #endregion Private Fields + + #region Public Constructors + + public CrmPluginAssembly(CrmOrganization org) + { + m_org = org; + CustomizationLevel = 1; + } + + public CrmPluginAssembly(CrmOrganization org, Guid id, string name, DateTime? createdOn, DateTime? modifiedOn, + CrmAssemblySourceType type, CrmAssemblyIsolationMode isolationMode, string path, string version, + string publicKeyToken, string culture, int customizationLevel, bool enabled) + : this(org) + { + AssemblyId = id; + Name = name; + SourceType = type; + ServerFileName = path; + Version = version; + PublicKeyToken = publicKeyToken; + Culture = culture; + CustomizationLevel = customizationLevel; + Enabled = enabled; + UpdateDates(createdOn, modifiedOn); + } + + public CrmPluginAssembly(CrmOrganization org, PluginAssembly assembly) + : this(org) + { + RefreshFromPluginAssembly(assembly); + } + + #endregion Public Constructors + + #region Public Properties + + [XmlIgnore] + [Browsable(false)] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Name", "Name", typeof(string)), + new CrmEntityColumn("Description", "Description", typeof(string)), + new CrmEntityColumn("ModifiedOn", "Modified On", typeof(string)), + new CrmEntityColumn("SourceType", "Source", typeof(string)), + new CrmEntityColumn("Version", "Version", typeof(string)), + new CrmEntityColumn("Path", "Path", typeof(string)), + new CrmEntityColumn("PublicKeyToken", "Public Key Token", typeof(string)), + new CrmEntityColumn("Culture", "Culture", typeof(string)), + new CrmEntityColumn("IsolationMode", "Isolation Mode", typeof(string)), + new CrmEntityColumn("Enabled", "Enabled", typeof(bool)), + new CrmEntityColumn("Id", "AssemblyId", typeof(Guid)), + }; + } + + return m_entityColumns; + } + } + + [Category("Information"), Browsable(true), Description("Unique identifier of Assembly"), ReadOnly(true)] + public Guid AssemblyId + { + get + { + return m_assemblyId; + } + set + { + if (value == m_assemblyId) + { + return; + } + + m_assemblyId = value; + + if (m_pluginList != null) + { + foreach (CrmPlugin plugin in m_pluginList.Values) + { + plugin.AssemblyId = value; + } + } + } + } + + /// + /// Retrieves the Created On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn { get; private set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Culture { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int CustomizationLevel + { + get + { + return m_customizationLevel; + } + + set + { + if (value < 0) + { + throw new ArgumentException("Invalid CustomizationLevel specified"); + } + + //If the customization level is 0, then this is a system assembly (which will depend on the current version of CRM) + if (0 == value && null == SdkVersion) + { + SdkVersion = Organization.ServerBuild; + } + + m_customizationLevel = value; + } + } + + [Category("Editable"), Browsable(true), Description("Description of the Assembly"), ReadOnly(false)] + public string Description { get; set; } + + [Browsable(false)] + public bool Enabled { get; set; } + + [XmlIgnore] + [Browsable(false)] + public Guid EntityId + { + get + { + return AssemblyId; + } + } + + [XmlIgnore] + [Browsable(false)] + public string EntityType + { + get + { + return PluginAssembly.EntityLogicalName; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmAssemblyIsolationMode IsolationMode { get; set; } + + [Browsable(false)] + public bool IsProfilerAssembly { get; set; } + + [XmlIgnore] + public bool IsSystemCrmEntity + { + get + { + return CustomizationLevel == 0; + } + } + + /// + /// Retrieves the Modified On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn { get; private set; } + + [Category("Information"), Browsable(true), Description("Name of the Assembly"), ReadOnly(true)] + public string Name + { + get + { + return m_Name; + } + set + { + if (value == m_Name) + { + return; + } + + m_Name = value; + + if (m_pluginList != null) + { + foreach (CrmPlugin plugin in m_pluginList.Values) + { + plugin.AssemblyName = value; + } + } + } + } + + [Browsable(false)] + public CrmOrganization Organization + { + get + { + return m_org; + } + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + else if (m_org == null) + { + m_org = value; + foreach (CrmPlugin plugin in m_pluginList.Values) + { + if (plugin.Organization == null) + { + plugin.Organization = m_org; + } + m_org.AddPlugin(this, plugin); + } + } + else + { + throw new NotSupportedException("Cannot change the Organization once it has been set"); + } + } + } + + [Browsable(false)] + public CrmEntityDictionary Plugins + { + get + { + if (m_pluginReadOnlyList == null) + { + m_pluginReadOnlyList = new CrmEntityDictionary(m_pluginList); + } + + return m_pluginReadOnlyList; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string PublicKeyToken { get; set; } + + [Category("Information"), DisplayName("SDK Version"), Description("Version of the CRM SDK Assemblies referenced by this Assembly.")] + [Browsable(true), ReadOnly(true)] + public Version SdkVersion { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string ServerFileName { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmAssemblySourceType SourceType { get; set; } + + [XmlIgnore] + [Browsable(false)] + public Dictionary Values + { + get + { + Dictionary valueList = new Dictionary(); + valueList.Add("Id", AssemblyId); + valueList.Add("Description", String.IsNullOrEmpty(Description) ? string.Empty : Description); + valueList.Add("Name", Name); + valueList.Add("ModifiedOn", + (ModifiedOn.HasValue ? ModifiedOn.ToString() : "")); + valueList.Add("SourceType", SourceType.ToString()); + valueList.Add("Version", ConvertNullStringToEmpty(Version)); + valueList.Add("Path", ConvertNullStringToEmpty(ServerFileName)); + valueList.Add("PublicKeyToken", ConvertNullStringToEmpty(PublicKeyToken)); + valueList.Add("Culture", ConvertNullStringToEmpty(Culture)); + + if (CrmAssemblyIsolationMode.Sandbox == IsolationMode) + { + valueList.Add("IsolationMode", "Sandbox"); + } + else + { + valueList.Add("IsolationMode", "None"); + } + + valueList.Add("Enabled", Enabled); + + return valueList; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Version { get; set; } + + #endregion Public Properties + + #region Public Indexers + + [Browsable(false)] + public CrmPlugin this[Guid pluginId] + { + get + { + return m_pluginList[pluginId]; + } + } + + #endregion Public Indexers + + #region Public Methods + + public void AddPlugin(CrmPlugin plugin) + { + if (plugin == null) + { + throw new ArgumentNullException("plugin"); + } + + m_pluginList.Add(plugin.PluginId, plugin); + + if (m_org != null) + { + Organization.AddPlugin(this, plugin); + } + } + + public void ClearPlugins() + { + m_pluginList.Clear(); + + if (m_org != null) + { + Organization.ClearPlugins(AssemblyId); + } + } + + public object Clone() + { + return Clone(true); + } + + public CrmPluginAssembly Clone(bool includeOrganization) + { + CrmPluginAssembly newAssembly; + if (includeOrganization) + { + newAssembly = new CrmPluginAssembly(m_org); + } + else + { + newAssembly = new CrmPluginAssembly(null); + } + + newAssembly.m_assemblyId = m_assemblyId; + newAssembly.m_Name = m_Name; + newAssembly.CreatedOn = CreatedOn; + newAssembly.Culture = Culture; + newAssembly.CustomizationLevel = m_customizationLevel; + newAssembly.Enabled = Enabled; + newAssembly.IsolationMode = IsolationMode; + newAssembly.ModifiedOn = ModifiedOn; + newAssembly.ServerFileName = ServerFileName; + newAssembly.PublicKeyToken = PublicKeyToken; + newAssembly.SourceType = SourceType; + newAssembly.Version = Version; + + //Create a new plugin list + Dictionary newPluginList = new Dictionary(); + foreach (CrmPlugin plugin in m_pluginList.Values) + { + //Clone the plugin + CrmPlugin clonedPlugin = (CrmPlugin)plugin.Clone(includeOrganization); + + //Add the plugin to the new list + newPluginList.Add(clonedPlugin.PluginId, clonedPlugin); + } + + //Assign the list to the new object + newAssembly.m_pluginList = newPluginList; + + return newAssembly; + } + + public Dictionary GenerateCrmEntities() + { + Dictionary entityList = new Dictionary(); + + PluginAssembly assembly = new PluginAssembly(); + if (AssemblyId != Guid.Empty) + { + assembly.PluginAssemblyId = new Guid?(); + assembly["pluginassemblyid"] = AssemblyId; + } + + assembly.SourceType = new OptionSetValue(); + assembly.SourceType.Value = (int)SourceType; + + assembly.IsolationMode = new OptionSetValue(); + assembly.IsolationMode.Value = (int)IsolationMode; + + assembly.Culture = Culture; + assembly.PublicKeyToken = PublicKeyToken; + assembly.Version = Version; + assembly.Name = Name; + assembly.Description = Description; + + if (AssemblyId != Guid.Empty) + { + assembly.PluginAssemblyId = new Guid?(); + assembly["pluginassemblyid"] = AssemblyId; + } + + switch (SourceType) + { + case CrmAssemblySourceType.Disk: + assembly.Path = ServerFileName; + break; + + case CrmAssemblySourceType.Database: + //Do nothing in this method + break; + + case CrmAssemblySourceType.GAC: + //Do nothing + break; + + default: + throw new NotImplementedException("SourceType = " + SourceType.ToString()); + } + + entityList.Add(PluginAssembly.EntityLogicalName, assembly); + + return entityList; + } + + public void RefreshFromPluginAssembly(PluginAssembly assembly) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + if (assembly.Name != null) + { + Name = assembly.Name; + } + + if (assembly.PluginAssemblyId != null) + { + AssemblyId = assembly.PluginAssemblyId.Value; + } + + if (assembly.CreatedOn != null && (assembly.CreatedOn.HasValue)) + { + CreatedOn = assembly.CreatedOn.Value; + } + + if (assembly.ModifiedOn != null && (assembly.ModifiedOn.HasValue)) + { + ModifiedOn = assembly.ModifiedOn.Value; + } + + if (assembly.SourceType != null) + { + SourceType = (CrmAssemblySourceType)Enum.ToObject(typeof(CrmAssemblySourceType), assembly.SourceType.Value); + } + + if (assembly.IsolationMode != null) + { + IsolationMode = (CrmAssemblyIsolationMode)Enum.ToObject(typeof(CrmAssemblyIsolationMode), + assembly.IsolationMode.Value); + } + + if (assembly.Path != null) + { + ServerFileName = assembly.Path; + } + + if (assembly.Version != null) + { + Version = assembly.Version; + } + + if (assembly.PublicKeyToken != null) + { + PublicKeyToken = assembly.PublicKeyToken; + } + + if (assembly.Culture != null) + { + Culture = assembly.Culture; + } + + if (assembly.CustomizationLevel != null) + { + CustomizationLevel = assembly.CustomizationLevel.Value; + } + + Description = assembly.Description; + + if (null == SdkVersion && CrmAssemblyIsolationMode.Sandbox == IsolationMode && + null != m_org) + { + //Sandbox was not supported in CRM 4. It is safe to assume CRM 2011 is used here. + //TODO: When the next version of CRM rolls out, will this assumption create problems? + SdkVersion = new Version(5, 0); + } + } + + public void RemovePlugin(Guid pluginId) + { + if (m_pluginList.ContainsKey(pluginId)) + { + m_pluginList.Remove(pluginId); + + if (m_org != null) + { + Organization.RemovePlugin(this, pluginId); + } + } + else + { + throw new ArgumentException("Invalid Plugin Id", "pluginId"); + } + } + + public override string ToString() + { + return NodeText; + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + CreatedOn = createdOn; + } + + if (modifiedOn != null) + { + ModifiedOn = modifiedOn; + } + } + + #endregion Public Methods + + #region Private Methods + + private string ConvertNullStringToEmpty(string val) + { + if (string.IsNullOrEmpty(val)) + { + return string.Empty; + } + else + { + return val; + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmPluginImage.cs b/Ofscrm.PluginRegistration/Wrappers/CrmPluginImage.cs new file mode 100644 index 0000000..5606b56 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmPluginImage.cs @@ -0,0 +1,706 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Xml.Serialization; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public enum CrmPluginImageType + { + PreImage = 0, + PostImage = 1, + Both = 2 + } + + public sealed class CrmPluginImage : ICrmEntity, ICloneable + { + #region Private Fields + + private static CrmEntityColumn[] m_entityColumns = null; + private Guid m_assemblyId = Guid.Empty; + private string m_attributes = null; + private DateTime? m_createdOn = null; + private int m_customizationLevel = 1; + private string m_entityAlias = null; + private Guid m_imageId = Guid.Empty; + private DateTime? m_modifiedOn = null; + private CrmOrganization m_org; + private Guid m_pluginId = Guid.Empty; + private string m_propertyName; + private string m_propertyTitle = null; + private string m_relatedAttribute = null; + private Guid m_stepId = Guid.Empty; + private CrmPluginImageType m_type = CrmPluginImageType.PostImage; + + #endregion Private Fields + + #region Public Constructors + + public CrmPluginImage(CrmOrganization org) + { + m_org = org; + } + + public CrmPluginImage(CrmOrganization org, Guid assemblyId, Guid pluginId, Guid stepId, Guid imageId, string attributes, + string relatedAttribute, string entityAlias, CrmPluginImageType imageType, string messagePropertyName, int customizationLevel, + DateTime? createdOn, DateTime? modifiedOn) + : this(org) + { + AssemblyId = assemblyId; + PluginId = pluginId; + StepId = stepId; + ImageId = imageId; + Attributes = attributes; + RelatedAttribute = relatedAttribute; + EntityAlias = entityAlias; + ImageType = imageType; + MessagePropertyName = messagePropertyName; + CustomizationLevel = customizationLevel; + UpdateDates(createdOn, modifiedOn); + } + + public CrmPluginImage(CrmOrganization org, Guid assemblyId, Guid pluginId, SdkMessageProcessingStepImage image) + : this(org) + { + RefreshFromSdkMessageProcessingStepImage(assemblyId, pluginId, image); + } + + #endregion Public Constructors + + #region Public Properties + + [XmlIgnore] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Name", "Name", typeof(string)), + new CrmEntityColumn("EntityAlias", "Entity Alias", typeof(string)), + new CrmEntityColumn("Type", "Image Type", typeof(string)), + new CrmEntityColumn("Attributes", "Attributes", typeof(string)), + new CrmEntityColumn("PropertyName", "Property Name", typeof(string)) , + new CrmEntityColumn("Id", "ImageId", typeof(Guid))}; + } + + return m_entityColumns; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid AssemblyId + { + get + { + return m_assemblyId; + } + + set + { + m_assemblyId = value; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Attributes + { + get + { + return m_attributes; + } + + set + { + m_attributes = value; + } + } + + /// + /// Retrieves the Created On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn + { + get + { + return m_createdOn; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int CustomizationLevel + { + get + { + return m_customizationLevel; + } + + set + { + if (value < 0) + { + throw new ArgumentException("Invalid CustomizationLevel specified"); + } + + m_customizationLevel = value; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string EntityAlias + { + get + { + return m_entityAlias; + } + + set + { + m_entityAlias = value; + } + } + + [XmlIgnore] + [Browsable(false)] + public Guid EntityId + { + get + { + return m_imageId; + } + } + + [XmlIgnore] + [Browsable(false)] + public string EntityType + { + get + { + return SdkMessageProcessingStepImage.EntityLogicalName; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid ImageId + { + get + { + return m_imageId; + } + + set + { + m_imageId = value; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginImageType ImageType + { + get + { + return m_type; + } + + set + { + m_type = value; + } + } + + [XmlIgnore] + [Category("Information"), Browsable(true), ReadOnly(true)] + public bool IsSystemCrmEntity + { + get + { + return CustomizationLevel == 0; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string MessagePropertyName + { + get + { + return m_propertyName; + } + + set + { + if (!string.Equals(m_propertyName, value)) + { + m_propertyName = value; + m_propertyTitle = null; + } + } + } + + /// + /// Retrieves the Modified On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn + { + get + { + return m_modifiedOn; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Name + { + get; + set; + } + + [XmlIgnore] + [Browsable(false)] + public Guid NodeId + { + get + { + return m_imageId; + } + } + + [XmlIgnore] + [Browsable(false)] + public string NodeText + { + get + { + string attributeList = m_attributes; + if (string.IsNullOrEmpty(attributeList)) + { + attributeList = null; + } + else if (attributeList.Length > 100) + { + attributeList = string.Format("{0}...", attributeList.Substring(0, 97)); + } + + string imageLabel; + switch (ImageType) + { + case CrmPluginImageType.PreImage: + imageLabel = "Pre Image"; + break; + + case CrmPluginImageType.PostImage: + imageLabel = "Post Image"; + break; + + case CrmPluginImageType.Both: + imageLabel = "Pre & Post Image"; + break; + + default: + throw new NotImplementedException("ImageType = " + ImageType.ToString()); + } + + //Retrieve the MessagePropertyName object + if (m_propertyTitle == null) + { + if (string.IsNullOrEmpty(MessagePropertyName)) + { + m_propertyTitle = string.Empty; + } + else if (Organization != null && Organization.Steps.ContainsKey(StepId)) + { + CrmPluginStep step = Organization.Steps[StepId]; + + Guid messageId; + string primaryEntity; + if (Guid.Empty == step.MessageEntityId) + { + messageId = step.MessageId; + primaryEntity = null; + } + else + { + CrmMessageEntity messageEntity = Organization.MessageEntities[step.MessageEntityId]; + messageId = messageEntity.MessageId; + primaryEntity = messageEntity.PrimaryEntity; + } + + m_propertyTitle = string.Empty; + + //Determine the title of the property + List validProperties = m_org.Messages[messageId].ImageMessagePropertyNames; + if (0 != validProperties.Count && !string.IsNullOrEmpty(m_propertyName)) + { + foreach (ImageMessagePropertyName property in validProperties) + { + if (string.Equals(property.Name, m_propertyName, StringComparison.OrdinalIgnoreCase)) + { + m_propertyTitle = property.Label; + break; + } + } + } + } + else + { + m_propertyTitle = null; + } + } + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("({0}) ", NodeTypeLabel); + if (!string.IsNullOrEmpty(m_entityAlias)) + { + sb.Append(EntityAlias); + } + else + { + sb.Append(imageLabel); + } + + if (!string.IsNullOrEmpty(attributeList)) + { + sb.AppendFormat(" ({0})", attributeList); + } + + if (!string.IsNullOrEmpty(m_propertyTitle)) + { + sb.AppendFormat(" - {0}", m_propertyTitle); + } + + return sb.ToString(); + } + } + + [XmlIgnore] + [Browsable(false)] + public string NodeTypeLabel + { + get + { + return "Image"; + } + } + + [Browsable(false)] + public CrmOrganization Organization + { + get + { + return m_org; + } + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + else if (m_org == null) + { + m_org = value; + } + else + { + throw new NotSupportedException("Cannot change the Organization once it has been set"); + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid PluginId + { + get + { + return m_pluginId; + } + + set + { + m_pluginId = value; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string RelatedAttribute + { + get + { + return m_relatedAttribute; + } + + set + { + m_relatedAttribute = value; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid StepId + { + get + { + return m_stepId; + } + + set + { + m_stepId = value; + } + } + + [XmlIgnore] + [Browsable(false)] + public Dictionary Values + { + get + { + Dictionary valueList = new Dictionary(); + valueList.Add("Id", ImageId); + valueList.Add("Name", String.IsNullOrEmpty(Name) ? string.Empty : Name); + valueList.Add("EntityAlias", EntityAlias); + valueList.Add("PropertyName", MessagePropertyName); + + if (string.IsNullOrEmpty(Attributes)) + { + valueList.Add("Attributes", "All Attributes"); + } + else + { + valueList.Add("Attributes", Attributes); + } + + switch (ImageType) + { + case CrmPluginImageType.PreImage: + + valueList.Add("Type", "Pre Image"); + break; + + case CrmPluginImageType.PostImage: + + valueList.Add("Type", "Post Image"); + break; + + case CrmPluginImageType.Both: + + valueList.Add("Type", "Pre & Post Image"); + break; + + default: + throw new NotImplementedException("ImageType = " + ImageType.ToString()); + } + + return valueList; + } + } + + #endregion Public Properties + + #region Public Methods + + public object Clone() + { + return Clone(true); + } + + public CrmPluginImage Clone(bool includeOrganization) + { + CrmPluginImage newImage; + if (includeOrganization) + { + newImage = new CrmPluginImage(m_org); + } + else + { + newImage = new CrmPluginImage(null); + } + + newImage.m_assemblyId = m_assemblyId; + newImage.m_attributes = m_attributes; + newImage.m_createdOn = m_createdOn; + newImage.m_customizationLevel = m_customizationLevel; + newImage.m_entityAlias = m_entityAlias; + newImage.m_imageId = m_imageId; + newImage.m_modifiedOn = m_modifiedOn; + newImage.m_pluginId = m_pluginId; + newImage.m_propertyName = m_propertyName; + newImage.m_propertyTitle = m_propertyTitle; + newImage.m_relatedAttribute = m_relatedAttribute; + newImage.m_stepId = m_stepId; + newImage.m_type = m_type; + + return newImage; + } + + public Dictionary GenerateCrmEntities() + { + if (Organization != null) + { + CrmPluginStep step = Organization[AssemblyId][PluginId][StepId]; + return GenerateCrmEntities(step.MessageId, step.MessageEntityId); + } + return GenerateCrmEntities(Guid.Empty, Guid.Empty); + } + + public Dictionary GenerateCrmEntities(Guid sdkMessageId, Guid sdkMessageFilterId) + { + if (Organization != null) + { + if (string.IsNullOrEmpty(MessagePropertyName)) + { + List validImages = Organization.Messages[sdkMessageId].ImageMessagePropertyNames; + if (0 != validImages.Count) + { + //Select the first one from the list + MessagePropertyName = validImages[0].Name; + } + } + } + + Dictionary entityList = new Dictionary(); + SdkMessageProcessingStepImage image = new SdkMessageProcessingStepImage(); + if (ImageId != Guid.Empty) + { + image.SdkMessageProcessingStepImageId = new Guid?(); + image["sdkmessageprocessingstepimageid"] = ImageId; + } + + if (StepId != Guid.Empty) + { + image.SdkMessageProcessingStepId = new EntityReference(); + image.SdkMessageProcessingStepId.LogicalName = SdkMessageProcessingStep.EntityLogicalName; + image.SdkMessageProcessingStepId.Id = StepId; + } + + image.ImageType = new OptionSetValue(); + image.ImageType.Value = (int)ImageType; + + image.MessagePropertyName = MessagePropertyName; + + image.Name = Name; + + image.EntityAlias = EntityAlias; + + if (!string.IsNullOrEmpty(Attributes)) // null is all attributes + { + image.Attributes1 = Attributes; + } + else + { + image.Attributes1 = string.Empty; + } + if (!string.IsNullOrEmpty(RelatedAttribute)) + { + image.RelatedAttributeName = RelatedAttribute; //For Related Entity Information + } + + entityList.Add(SdkMessageProcessingStepImage.EntityLogicalName, image); + + return entityList; + } + + public void RefreshFromSdkMessageProcessingStepImage(Guid assemblyId, Guid pluginId, SdkMessageProcessingStepImage image) + { + if (image == null) + { + throw new ArgumentNullException("image"); + } + + AssemblyId = assemblyId; + PluginId = pluginId; + + if (image.SdkMessageProcessingStepImageId != null) + { + ImageId = image.SdkMessageProcessingStepImageId.Value; + } + + if (image.Attributes != null) + { + Attributes = image.Attributes1; + } + + if (image.EntityAlias != null) + { + EntityAlias = image.EntityAlias; + } + + if (image.MessagePropertyName != null) + { + MessagePropertyName = image.MessagePropertyName; + } + + if (image.RelatedAttributeName != null) + { + RelatedAttribute = image.RelatedAttributeName; + } + + if (image.SdkMessageProcessingStepId != null) + { + StepId = image.SdkMessageProcessingStepId.Id; + } + + if (image.ImageType != null) + { + ImageType = (CrmPluginImageType)Enum.ToObject(typeof(CrmPluginImageType), image.ImageType.Value); + } + + if (image.CustomizationLevel != null) + { + m_customizationLevel = image.CustomizationLevel.Value; + } + + if (image.CreatedOn != null && (image.CreatedOn.HasValue)) + { + m_createdOn = image.CreatedOn.Value; + } + + if (image.ModifiedOn != null && (image.ModifiedOn.HasValue)) + { + m_modifiedOn = image.ModifiedOn.Value; + } + + Name = image.Name; + } + + public override string ToString() + { + return NodeText; + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + m_createdOn = createdOn; + } + + if (modifiedOn != null) + { + m_modifiedOn = modifiedOn; + } + } + + #endregion Public Methods + + #region Private Methods + + private string ConvertNullStringToEmpty(string val) + { + if (string.IsNullOrEmpty(val)) + { + return string.Empty; + } + else + { + return val; + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmPluginStep.cs b/Ofscrm.PluginRegistration/Wrappers/CrmPluginStep.cs new file mode 100644 index 0000000..90eca15 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmPluginStep.cs @@ -0,0 +1,1033 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; +using Microsoft.Xrm.Sdk; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public sealed class CrmPluginStep : ICrmEntity, ICloneable + { + public const string RelationshipStepToSecureConfig = "sdkmessageprocessingstepsecureconfigid_sdkmessageprocessingstep"; + public const string RelationshipStepToImage = "sdkmessageprocessingstepid_sdkmessageprocessingstepimage"; + + private CrmOrganization m_org; + private Guid m_assemblyId = Guid.Empty; + private Guid m_pluginId = Guid.Empty; + private int m_customizationLevel = 1; + private string m_filteringAttributes = null; + private DateTime? m_createdOn = null; + private DateTime? m_modifiedOn = null; + private Guid m_serviceBusConfigurationId = Guid.Empty; + + private CrmEntityDictionary m_imageReadOnlyList = null; + private Dictionary m_imageList = new Dictionary(); + + public CrmPluginStep(CrmOrganization org) + { + m_org = org; + Enabled = true; + Mode = CrmPluginStepMode.Synchronous; + Stage = CrmPluginStepStage.PostOperationDeprecated; + Rank = 1; + Deployment = CrmPluginStepDeployment.ServerOnly; + } + + public CrmPluginStep(CrmOrganization org, Guid assemblyId, Guid pluginId, Guid stepId, Guid messageId, Guid messageEntityId, + string name, string unsecureConfiguration, Guid secureConfigurationId, string secureConfiguration, + Guid impersonatingUserId, CrmPluginStepMode mode, CrmPluginStepStage stage, + CrmPluginStepDeployment deployment, CrmPluginStepInvocationSource? invocationSource, int rank, bool enabled, + int customizationLevel, DateTime? createdOn, DateTime? modifiedOn, string filteringAttributes, Guid serviceBusConfigurationId) + : this(org) + { + AssemblyId = assemblyId; + Deployment = deployment; + Name = name; + Enabled = enabled; + ImpersonatingUserId = impersonatingUserId; + InvocationSource = invocationSource; + MessageEntityId = messageEntityId; + MessageId = messageId; + Mode = mode; + PluginId = pluginId; + Rank = rank; + SecureConfigurationId = secureConfigurationId; + SecureConfiguration = secureConfiguration; + Stage = stage; + StepId = stepId; + CustomizationLevel = customizationLevel; + UnsecureConfiguration = unsecureConfiguration; + FilteringAttributes = filteringAttributes; + m_createdOn = createdOn; + m_modifiedOn = modifiedOn; + m_serviceBusConfigurationId = serviceBusConfigurationId; + } + + public CrmPluginStep(CrmOrganization org, Guid assemblyId, SdkMessageProcessingStep step, string secureConfig) + : this(org) + { + if (step == null) + { + throw new ArgumentNullException("step"); + } + + RefreshFromSdkMessageProcessingStep(assemblyId, step, secureConfig); + } + + #region Properties + + /// + /// Retrieves the Created On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? CreatedOn + { + get + { + return m_createdOn; + } + } + + /// + /// Retrieves the Modified On date of the entity. To update, see UpdateDates. + /// + [Category("Information"), Browsable(true), ReadOnly(true)] + public DateTime? ModifiedOn + { + get + { + return m_modifiedOn; + } + } + + [Browsable(false)] + public CrmOrganization Organization + { + get + { + return m_org; + } + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + else if (m_org == null) + { + m_org = value; + foreach (CrmPluginImage image in m_imageList.Values) + { + if (image.Organization == null) + { + image.Organization = m_org; + } + m_org.AddImage(this, image); + } + } + else + { + throw new NotSupportedException("Cannot change the Organization once it has been set"); + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid AssemblyId + { + get + { + return m_assemblyId; + } + + set + { + if (value == m_assemblyId) + { + return; + } + + m_assemblyId = value; + + if (m_imageList != null) + { + foreach (CrmPluginImage image in m_imageList.Values) + { + image.AssemblyId = value; + } + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid PluginId + { + get + { + return m_pluginId; + } + + set + { + if (value == m_pluginId) + { + return; + } + + m_pluginId = value; + + if (m_imageList != null) + { + foreach (CrmPluginImage image in m_imageList.Values) + { + image.PluginId = value; + } + } + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public EntityReference EventHandler { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid ServiceBusConfigurationId + { + get + { + return m_serviceBusConfigurationId; + } + + set + { + m_serviceBusConfigurationId = value; + } + } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid StepId { get; set; } + + [Browsable(false)] + public bool Enabled { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginStepMode Mode { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginStepStage Stage { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid MessageId { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int Rank { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string FilteringAttributes { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginStepDeployment Deployment { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public CrmPluginStepInvocationSource? InvocationSource { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Name { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string Description { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string UnsecureConfiguration { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid SecureConfigurationId { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public string SecureConfiguration { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid ImpersonatingUserId { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public Guid MessageEntityId { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public bool DeleteAsyncOperationIfSuccessful { get; set; } + + [Category("Information"), Browsable(true), ReadOnly(true)] + public int CustomizationLevel + { + get + { + return m_customizationLevel; + } + + set + { + if (value < 0) + { + throw new ArgumentException("Invalid CustomizationLevel specified"); + } + + m_customizationLevel = value; + } + } + + [Browsable(false)] + public CrmPluginImage this[Guid imageId] + { + get + { + return m_imageList[imageId]; + } + } + + [Browsable(false)] + public CrmEntityDictionary Images + { + get + { + if (m_imageReadOnlyList == null) + { + m_imageReadOnlyList = new CrmEntityDictionary(m_imageList); + } + + return m_imageReadOnlyList; + } + } + + [XmlIgnore] + [Browsable(false)] + public bool SecureConfigurationRecordIdInvalid { get; set; } + + [Browsable(false)] + public bool IsProfiled + { + get + { + return (null != ProfilerStepId); + } + } + + [Browsable(false)] + public Guid? ProfilerStepId { get; set; } + + /// + /// ID for the Step that is being profiled + /// + [Browsable(false)] + public Guid? ProfilerOriginalStepId { get; set; } + + #endregion Properties + + #region Public Helper Methods + + public void RefreshFromSdkMessageProcessingStep(Guid assemblyId, SdkMessageProcessingStep step, string secureConfig) + { + if (step == null) + { + throw new ArgumentNullException("step"); + } + + if (step.SupportedDeployment != null) + { + Deployment = (CrmPluginStepDeployment)Enum.ToObject(typeof(CrmPluginStepDeployment), step.SupportedDeployment.Value); + } + + if (step.StateCode != null) + { + Enabled = (step.StateCode.Value == SdkMessageProcessingStepState.Enabled); + } + + if (step.ImpersonatingUserId != null) + { + ImpersonatingUserId = step.ImpersonatingUserId.Id; + } + +#pragma warning disable 0612 + if (step.InvocationSource != null) + { + InvocationSource = (CrmPluginStepInvocationSource)Enum.ToObject(typeof(CrmPluginStepInvocationSource), step.InvocationSource.Value); + } +#pragma warning restore 0612 + + if (step.SdkMessageFilterId != null) + { + MessageEntityId = step.SdkMessageFilterId.Id; + } + + if (step.SdkMessageId != null) + { + MessageId = step.SdkMessageId.Id; + } + + if (step.Mode != null) + { + Mode = (CrmPluginStepMode)Enum.ToObject(typeof(CrmPluginStepMode), step.Mode.Value); + } + + if (step.CreatedOn != null && (step.CreatedOn.HasValue)) + { + m_createdOn = step.CreatedOn.Value; + } + + if (step.ModifiedOn != null && (step.ModifiedOn.HasValue)) + { + m_modifiedOn = step.ModifiedOn.Value; + } + +#pragma warning disable 0612 + if (step.PluginTypeId != null) + { + PluginId = step.PluginTypeId.Id; + } +#pragma warning restore 0612 + + if (step.Rank != null && (step.Rank.HasValue)) + { + Rank = step.Rank.Value; + } + + if (step.SdkMessageProcessingStepSecureConfigId != null) + { + SecureConfigurationId = step.SdkMessageProcessingStepSecureConfigId.Id; + SecureConfiguration = secureConfig; + } + else + { + SecureConfiguration = null; + SecureConfigurationId = Guid.Empty; + } + + // Step can be unregistered as ExchangeRate plugin Can be replaced to ISV Plugin. So 'customizationlevel' logic is no longer valid here. + CustomizationLevel = 1; + + if (step.Stage != null) + { + Stage = (CrmPluginStepStage)Enum.ToObject(typeof(CrmPluginStepStage), step.Stage.Value); + } + + AssemblyId = assemblyId; + + if (step.SdkMessageProcessingStepId != null) + { + StepId = step.SdkMessageProcessingStepId.Value; + } + + if (step.Configuration != null) + { + UnsecureConfiguration = step.Configuration; + } + else + { + UnsecureConfiguration = null; + } + + if (step.EventHandler != null) + { + EventHandler = step.EventHandler; + if (EventHandler.LogicalName == ServiceEndpoint.EntityLogicalName) + { + ServiceBusConfigurationId = step.EventHandler.Id; + } + } + + Name = step.Name; + + Description = step.Description; + + FilteringAttributes = step.FilteringAttributes; + + if (step.AsyncAutoDelete != null) + { + DeleteAsyncOperationIfSuccessful = (bool)step.AsyncAutoDelete; + } + } + + public override string ToString() + { + return NodeText; + } + + #region Management Methods + + public void AddImage(CrmPluginImage image) + { + if (image == null) + { + throw new ArgumentNullException("image"); + } + + m_imageList.Add(image.ImageId, image); + + if (Organization != null) + { + Organization.AddImage(this, image); + } + } + + public void ClearImages() + { + m_imageList.Clear(); + + if (Organization != null) + { + Organization.ClearImages(StepId); + } + } + + public void RemoveImage(Guid imageId) + { + if (m_imageList.ContainsKey(imageId)) + { + m_imageList.Remove(imageId); + + if (Organization != null) + { + Organization.RemoveImage(this, imageId); + } + } + else + { + throw new ArgumentException("Invalid Image Id", "imageId"); + } + } + + #endregion Management Methods + + #endregion Public Helper Methods + + #region Private Helper Methods + + private string ConvertNullStringToEmpty(string val) + { + if (string.IsNullOrEmpty(val)) + { + return string.Empty; + } + else + { + return val; + } + } + + #endregion Private Helper Methods + + #region ICrmTreeItem Members + + [XmlIgnore] + [Browsable(false)] + public string NodeText + { + get + { + return string.Format("({0}) {1}", NodeTypeLabel, string.IsNullOrWhiteSpace(Name) ? Description : Name); + } + } + + [XmlIgnore] + [Browsable(false)] + public Guid NodeId + { + get + { + return StepId; + } + } + + [XmlIgnore] + [Browsable(false)] + public string NodeTypeLabel + { + get + { + return "Step"; + } + } + + #endregion ICrmTreeItem Members + + #region ICrmEntity Members + + [XmlIgnore] + [Browsable(false)] + public string EntityType + { + get + { + return SdkMessageProcessingStep.EntityLogicalName; + } + } + + [XmlIgnore] + [Browsable(false)] + public Guid EntityId + { + get + { + return StepId; + } + } + + public Dictionary GenerateCrmEntities() + { + Dictionary entityList = new Dictionary(); + //Check for Permissions denied + bool saveSecureConfiguration = true; + if (Organization != null) + { + saveSecureConfiguration = !Organization.SecureConfigurationPermissionDenied; + } + + //Create the secure configuration entity + SdkMessageProcessingStep sdkStep = new SdkMessageProcessingStep(); + // For Create cases, SecureConfig != null , SecureConfigurationId = null + + //For Update cases SecureConfigurationId != null , SecureConfig=null + if (!string.IsNullOrEmpty(SecureConfiguration)) + { + SdkMessageProcessingStepSecureConfig sdkSecureConfig = new SdkMessageProcessingStepSecureConfig(); + if (SecureConfigurationId != Guid.Empty) + { + sdkSecureConfig.SdkMessageProcessingStepSecureConfigId = new Guid?(); + sdkSecureConfig["sdkmessageprocessingstepsecureconfigid"] = SecureConfigurationId; + + sdkStep.SdkMessageProcessingStepSecureConfigId = new EntityReference(); + sdkStep.SdkMessageProcessingStepSecureConfigId.LogicalName = SdkMessageProcessingStepSecureConfig.EntityLogicalName; + sdkStep.SdkMessageProcessingStepSecureConfigId.Id = SecureConfigurationId; + } + + sdkSecureConfig.SecureConfig = SecureConfiguration; + + entityList.Add(SdkMessageProcessingStepSecureConfig.EntityLogicalName, sdkSecureConfig); + } + + //Create the main entity + if (StepId != Guid.Empty) + { + sdkStep.SdkMessageProcessingStepId = new Guid?(); + sdkStep["sdkmessageprocessingstepid"] = StepId; + } + + sdkStep.Configuration = UnsecureConfiguration; + + if (ServiceBusConfigurationId == Guid.Empty) + { + sdkStep.EventHandler = new EntityReference(PluginType.EntityLogicalName, PluginId); + } + else + { + sdkStep.EventHandler = new EntityReference(ServiceEndpoint.EntityLogicalName, ServiceBusConfigurationId); + } + + sdkStep.Name = Name; + + sdkStep.Mode = new OptionSetValue(); + sdkStep.Mode.Value = (int)Mode; + + sdkStep.Rank = new int?(); + sdkStep["rank"] = Rank; + + if (null != InvocationSource) + { +#pragma warning disable 0612 + sdkStep.InvocationSource = new OptionSetValue((int)InvocationSource); +#pragma warning restore 0612 + } + + sdkStep.SdkMessageId = new EntityReference(); + sdkStep.SdkMessageId.LogicalName = SdkMessage.EntityLogicalName; + + sdkStep.SdkMessageFilterId = new EntityReference(); + sdkStep.SdkMessageFilterId.LogicalName = SdkMessageFilter.EntityLogicalName; + + if (MessageId == Guid.Empty) + { + sdkStep.SdkMessageId = null; + } + else + { + sdkStep.SdkMessageId.Id = MessageId; + } + if (MessageEntityId == Guid.Empty) + { + sdkStep.SdkMessageFilterId = null; + } + else + { + sdkStep.SdkMessageFilterId.Id = MessageEntityId; + } + sdkStep.ImpersonatingUserId = new EntityReference(); + sdkStep.ImpersonatingUserId.LogicalName = SystemUser.EntityLogicalName; + + if (ImpersonatingUserId != Guid.Empty) + { + sdkStep.ImpersonatingUserId.Id = ImpersonatingUserId; + } + else + { + sdkStep.ImpersonatingUserId = null; + } + + sdkStep.Stage = new OptionSetValue(); + sdkStep.Stage.Value = (int)Stage; + + sdkStep.SupportedDeployment = new OptionSetValue(); + sdkStep.SupportedDeployment.Value = (int)Deployment; + + if (string.IsNullOrEmpty(FilteringAttributes)) + { + sdkStep.FilteringAttributes = string.Empty; + } + else + { + sdkStep.FilteringAttributes = FilteringAttributes; + } + + sdkStep.AsyncAutoDelete = DeleteAsyncOperationIfSuccessful; + + sdkStep.Description = Description; + + entityList.Add(SdkMessageProcessingStep.EntityLogicalName, sdkStep); + + return entityList; + } + + private static CrmEntityColumn[] m_entityColumns = null; + + [XmlIgnore] + public static CrmEntityColumn[] Columns + { + get + { + if (m_entityColumns == null) + { + m_entityColumns = new CrmEntityColumn[] { + new CrmEntityColumn("Name", "Name", typeof(string)), + new CrmEntityColumn("CreatedOn", "Created On", typeof(string)), + new CrmEntityColumn("ModifiedOn", "Modified On", typeof(string)), + new CrmEntityColumn("Message", "Message", typeof(string)), + new CrmEntityColumn("PrimaryEntity", "PrimaryEntity", typeof(string)), + new CrmEntityColumn("SecondaryEntity", "SecondaryEntity", typeof(string)), + new CrmEntityColumn("TypeName", "TypeName", typeof(string)), + new CrmEntityColumn("FilteringAttributes", "Filtering Attributes", typeof(string)), + new CrmEntityColumn("Impersonate", "Impersonate", typeof(string)), + new CrmEntityColumn("Mode", "Mode", typeof(string)), + new CrmEntityColumn("Deployment", "Deployment", typeof(string)), + new CrmEntityColumn("Invocation", "Invocation", typeof(string)), + new CrmEntityColumn("Stage", "Stage", typeof(string)), + new CrmEntityColumn("Enabled", "Enabled", typeof(bool)), + new CrmEntityColumn("Rank", "Rank", typeof(int)), + new CrmEntityColumn("Description", "Description", typeof(string)), + new CrmEntityColumn("UnsecureConfiguration", "Unsecure Configuration", typeof(string)), + new CrmEntityColumn("SecureConfiguration", "Secure Configuration", typeof(string)), + new CrmEntityColumn("MessageId", "MessageId", typeof(string)), + new CrmEntityColumn("MessageEntityId", "MessageEntityId", typeof(string)), + new CrmEntityColumn("Id", "StepId", typeof(Guid)), + new CrmEntityColumn("ServiceBusConfigurationId", "ServiceBus Config", typeof(Guid)), + new CrmEntityColumn("DeleteAsyncOperationIfSuccessful", "Delete Async.", typeof(string)) + }; + } + + return m_entityColumns; + } + } + + [XmlIgnore] + [Browsable(false)] + public Dictionary Values + { + get + { + Dictionary valueList = new Dictionary(); + valueList.Add("Id", StepId); + valueList.Add("Name", ConvertNullStringToEmpty(Name)); + valueList.Add("CreatedOn", CreatedOn.HasValue ? CreatedOn.ToString() : ""); + valueList.Add("ModifiedOn", ModifiedOn.HasValue ? ModifiedOn.ToString() : ""); + + if (MessageId == Guid.Empty) + { + valueList.Add("Message", string.Empty); + valueList.Add("MessageId", Guid.Empty.ToString()); + valueList.Add("MessageEntityId", MessageEntityId.ToString()); + valueList.Add("PrimaryEntity", string.Empty); + valueList.Add("SecondaryEntity", string.Empty); + } + else if (Organization == null) + { + valueList.Add("Message", MessageId.ToString()); + valueList.Add("MessageId", MessageId.ToString()); + valueList.Add("MessageEntityId", MessageEntityId.ToString()); + valueList.Add("PrimaryEntity", MessageEntityId.ToString()); + valueList.Add("SecondaryEntity", MessageEntityId.ToString()); + } + else + { + valueList.Add("MessageId", MessageId.ToString()); + valueList.Add("MessageEntityId", MessageEntityId.ToString()); + + if (Organization.Messages.ContainsKey(MessageId)) + { + valueList.Add("Message", Organization.Messages[MessageId].Name); + + if (Organization.Messages[MessageId].MessageEntities.ContainsKey(MessageEntityId)) + { + valueList.Add("PrimaryEntity", Organization.Messages[MessageId][MessageEntityId].PrimaryEntity); + valueList.Add("SecondaryEntity", Organization.Messages[MessageId][MessageEntityId].SecondaryEntity); + } + else if (MessageEntityId == Guid.Empty) + { + valueList.Add("PrimaryEntity", "none"); + valueList.Add("SecondaryEntity", "none"); + } + else + { + valueList.Add("PrimaryEntity", "Invalid MessageFilterId"); + valueList.Add("SecondaryEntity", "Invalid MessageFilterId"); + } + } + else + { + valueList.Add("Message", "Invalid Message"); + valueList.Add("PrimaryEntity", string.Empty); + valueList.Add("SecondaryEntity", string.Empty); + } + } + if (Organization != null && Organization.Plugins != null && Organization.Plugins.ContainsKey(PluginId)) + { + valueList.Add("TypeName", Organization.Plugins[PluginId].TypeName); + } + else + { + valueList.Add("TypeName", "Error - Unable to retrieve the TypeName"); + } + + if (ImpersonatingUserId == Guid.Empty) + { + valueList.Add("Impersonate", "Calling User"); + } + else if (Organization == null) + { + valueList.Add("Impersonate", ImpersonatingUserId.ToString()); + } + else if (Organization.Users.ContainsKey(ImpersonatingUserId)) + { + valueList.Add("Impersonate", Organization.Users[ImpersonatingUserId].Name); + } + else + { + valueList.Add("Impersonate", "Invalid User"); + } + valueList.Add("Mode", Mode.ToString()); + + switch (Stage) + { + case CrmPluginStepStage.PreValidation: + + valueList.Add("Stage", "Pre Stage - Outside Transaction"); + break; + + case CrmPluginStepStage.PreOperation: + + valueList.Add("Stage", "Pre Stage - Inside Transaction"); + break; + + case CrmPluginStepStage.PostOperation: + + valueList.Add("Stage", "Post Stage - Inside Transaction"); + break; + + case CrmPluginStepStage.PostOperationDeprecated: + + valueList.Add("Stage", "Post Stage - Outside Transaction"); + break; + + default: + throw new NotImplementedException("Stage = " + Stage.ToString()); + } + + switch (Deployment) + { + case CrmPluginStepDeployment.ServerOnly: + + valueList.Add("Deployment", "Server Only"); + break; + + case CrmPluginStepDeployment.OfflineOnly: + + valueList.Add("Deployment", "Offline Only"); + break; + + case CrmPluginStepDeployment.Both: + + valueList.Add("Deployment", "Server & Offline"); + break; + + default: + throw new NotImplementedException("Deployment = " + Deployment.ToString()); + } + + switch (InvocationSource) + { + case CrmPluginStepInvocationSource.Parent: + + valueList.Add("Invocation", "Parent Pipeline"); + break; + + case CrmPluginStepInvocationSource.Child: + + valueList.Add("Invocation", "Child Pipeline"); + break; + } + + valueList.Add("Enabled", Enabled); + valueList.Add("Rank", Rank); + + if (string.IsNullOrEmpty(FilteringAttributes)) + { + valueList.Add("FilteringAttributes", "All Attributes"); + } + else + { + valueList.Add("FilteringAttributes", FilteringAttributes); + } + + valueList.Add("Description", ConvertNullStringToEmpty(Description)); + valueList.Add("UnsecureConfiguration", ConvertNullStringToEmpty(UnsecureConfiguration)); + valueList.Add("ServiceBusConfigurationId", ServiceBusConfigurationId); + + if (Organization != null && Organization.SecureConfigurationPermissionDenied) + { + valueList.Add("SecureConfiguration", "Unable to Retrieve Value"); + } + else + { + valueList.Add("SecureConfiguration", ConvertNullStringToEmpty(SecureConfiguration)); + } + + if (DeleteAsyncOperationIfSuccessful) + { + valueList.Add("DeleteAsyncOperationIfSuccessful", "If StatusCode = Successful"); + } + else + { + valueList.Add("DeleteAsyncOperationIfSuccessful", "Manually"); + } + + return valueList; + } + } + + [XmlIgnore] + [Category("Information"), Browsable(true), ReadOnly(true)] + public bool IsSystemCrmEntity + { + get + { + return CustomizationLevel == 0; + } + } + + public void UpdateDates(DateTime? createdOn, DateTime? modifiedOn) + { + if (createdOn != null) + { + m_createdOn = createdOn; + } + + if (modifiedOn != null) + { + m_modifiedOn = modifiedOn; + } + } + + #endregion ICrmEntity Members + + #region ICloneable Members + + public object Clone() + { + return Clone(true); + } + + public CrmPluginStep Clone(bool includeOrganization) + { + CrmPluginStep newStep; + if (includeOrganization) + { + newStep = new CrmPluginStep(m_org); + } + else + { + newStep = new CrmPluginStep(null); + } + + newStep.m_assemblyId = m_assemblyId; + newStep.UnsecureConfiguration = UnsecureConfiguration; + newStep.m_createdOn = m_createdOn; + newStep.m_customizationLevel = m_customizationLevel; + newStep.Deployment = Deployment; + newStep.Name = Name; + newStep.Enabled = Enabled; + newStep.MessageEntityId = MessageEntityId; + newStep.m_filteringAttributes = m_filteringAttributes; + newStep.ImpersonatingUserId = ImpersonatingUserId; + newStep.InvocationSource = InvocationSource; + newStep.MessageId = MessageId; + newStep.Mode = Mode; + newStep.m_modifiedOn = m_modifiedOn; + newStep.m_pluginId = m_pluginId; + newStep.Rank = Rank; + newStep.SecureConfiguration = SecureConfiguration; + newStep.SecureConfigurationId = SecureConfigurationId; + newStep.Stage = Stage; + newStep.StepId = StepId; + newStep.m_serviceBusConfigurationId = m_serviceBusConfigurationId; + //Create a new image list + Dictionary newImageList = new Dictionary(); + foreach (CrmPluginImage image in m_imageList.Values) + { + //Clone the image + CrmPluginImage clonedImage = (CrmPluginImage)image.Clone(includeOrganization); + + //Add the image to the new list + newImageList.Add(clonedImage.ImageId, clonedImage); + } + + //Assign the list to the new object + newStep.m_imageList = newImageList; + + return newStep; + } + + #endregion ICloneable Members + } + + public enum CrmPluginStepMode + { + Asynchronous = 1, + Synchronous = 0 + } + + public enum CrmPluginStepStage + { + PreValidation = 10, + PreOperation = 20, + PostOperation = 40, + PostOperationDeprecated = 50 + } + + public enum CrmPluginStepDeployment + { + ServerOnly = 0, + OfflineOnly = 1, + Both = 2 + } + + public enum CrmPluginStepInvocationSource + { + Parent = 0, + Child = 1 + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/Wrappers/CrmUser.cs b/Ofscrm.PluginRegistration/Wrappers/CrmUser.cs new file mode 100644 index 0000000..15fc827 --- /dev/null +++ b/Ofscrm.PluginRegistration/Wrappers/CrmUser.cs @@ -0,0 +1,92 @@ +using System; +using Ofscrm.PluginRegistration.Entities; + +namespace Ofscrm.PluginRegistration.Wrappers +{ + public sealed class CrmUser + { + #region Private Fields + + private CrmOrganization m_org; + + #endregion Private Fields + + #region Public Constructors + + public CrmUser(CrmOrganization org) + { + if (org == null) + { + throw new ArgumentNullException("org"); + } + + m_org = org; + } + + public CrmUser(CrmOrganization org, SystemUser user) + : this(org) + { + if (user.SystemUserId != null) + { + UserId = user.SystemUserId.Value; + } + + Name = user.FullName; + + if (user.IsDisabled != null && (user.IsDisabled.HasValue)) + { + Enabled = !user.IsDisabled.Value; + } + + DomainName = user.DomainName; + InternalEmailAddress = user.InternalEMailAddress; + } + + #endregion Public Constructors + + #region Public Properties + + public string DomainName { get; set; } + + public bool Enabled { get; set; } + + public string InternalEmailAddress { get; set; } + + public string Name { get; set; } + + public CrmOrganization Organization + { + get + { + return m_org; + } + } + + public Guid UserId { get; set; } + + #endregion Public Properties + + #region Public Methods + + public override string ToString() + { + if (Enabled) + { + if (null != Name) + { + return Name; + } + else + { + return string.Format("null {0}", DomainName); + } + } + else + { + return string.Format("{0} (Disabled)", Name); + } + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/app.config b/Ofscrm.PluginRegistration/app.config new file mode 100644 index 0000000..e633bad --- /dev/null +++ b/Ofscrm.PluginRegistration/app.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ofscrm.PluginRegistration/packages.config b/Ofscrm.PluginRegistration/packages.config new file mode 100644 index 0000000..02f5ae3 --- /dev/null +++ b/Ofscrm.PluginRegistration/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/PluginRegistration.sln b/PluginRegistration.sln index 0e6a1aa..ad52acf 100644 --- a/PluginRegistration.sln +++ b/PluginRegistration.sln @@ -1,12 +1,16 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xrm.Sdk.PluginRegistration", "Xrm.Sdk.PluginRegistration\Xrm.Sdk.PluginRegistration.csproj", "{2E450060-2AC3-40A5-B6E5-2FD642886E18}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xrm.Sdk.PluginRegistration.Tests", "Xrm.Sdk.PluginRegistration.Tests\Xrm.Sdk.PluginRegistration.Tests.csproj", "{7C88B9FC-926A-4A47-9EE7-8DAFABE398F3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ofscrm.PluginRegistration", "Ofscrm.PluginRegistration\Ofscrm.PluginRegistration.csproj", "{48FC78F2-E0DA-4B04-B043-C69E9130A6A4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ofscrm.PluginRegistration.Tests", "Ofscrm.PluginRegistration.Tests\Ofscrm.PluginRegistration.Tests.csproj", "{80420FE9-F185-4DF2-A3BF-9DEBB341849B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +25,14 @@ Global {7C88B9FC-926A-4A47-9EE7-8DAFABE398F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C88B9FC-926A-4A47-9EE7-8DAFABE398F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {7C88B9FC-926A-4A47-9EE7-8DAFABE398F3}.Release|Any CPU.Build.0 = Release|Any CPU + {48FC78F2-E0DA-4B04-B043-C69E9130A6A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48FC78F2-E0DA-4B04-B043-C69E9130A6A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48FC78F2-E0DA-4B04-B043-C69E9130A6A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48FC78F2-E0DA-4B04-B043-C69E9130A6A4}.Release|Any CPU.Build.0 = Release|Any CPU + {80420FE9-F185-4DF2-A3BF-9DEBB341849B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80420FE9-F185-4DF2-A3BF-9DEBB341849B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80420FE9-F185-4DF2-A3BF-9DEBB341849B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80420FE9-F185-4DF2-A3BF-9DEBB341849B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE