diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor index d5f98e72..8b4cb758 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor @@ -55,7 +55,7 @@ protected override void OnInitialized() { - AddModuleMessage("Please Note That Once You Select The Create Module Button The Application Must Restart In Order To Complete The Process.", MessageType.Info); + AddModuleMessage("Please Note That Once You Select The Create Module Button The Application Must Restart In Order To Complete The Process. If You Create An External Module You Will Need To Compile The Source Code In Order To Make It Functional.", MessageType.Info); } private async Task CreateModule() diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs index 6f6bc85c..ed7c765b 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs @@ -11,7 +11,7 @@ namespace [Owner].[Module]s.Modules Description = "[Module]", Version = "1.0.0", Dependencies = "[Owner].[Module]s.Module.Shared", - ServerAssemblyName = "[ServerAssemblyName]" + ServerManagerType = "[ServerManagerType]" }; } } diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs index 9414847d..7265d4eb 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs @@ -6,7 +6,7 @@ using Oqtane.Models; using [Owner].[Module]s.Models; using [Owner].[Module]s.Repository; -namespace [Owner].[Module]s.Modules +namespace [Owner].[Module]s.Manager { public class [Module]Manager : IPortable { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs index 6f6bc85c..ed7c765b 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs @@ -11,7 +11,7 @@ namespace [Owner].[Module]s.Modules Description = "[Module]", Version = "1.0.0", Dependencies = "[Owner].[Module]s.Module.Shared", - ServerAssemblyName = "[ServerAssemblyName]" + ServerManagerType = "[ServerManagerType]" }; } } diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs index 9414847d..7265d4eb 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs @@ -6,7 +6,7 @@ using Oqtane.Models; using [Owner].[Module]s.Models; using [Owner].[Module]s.Repository; -namespace [Owner].[Module]s.Modules +namespace [Owner].[Module]s.Manager { public class [Module]Manager : IPortable { diff --git a/Oqtane.Client/Modules/HtmlText/ModuleInfo.cs b/Oqtane.Client/Modules/HtmlText/ModuleInfo.cs index 0d4ad914..48b674d5 100644 --- a/Oqtane.Client/Modules/HtmlText/ModuleInfo.cs +++ b/Oqtane.Client/Modules/HtmlText/ModuleInfo.cs @@ -7,9 +7,9 @@ namespace Oqtane.Modules.HtmlText public ModuleDefinition ModuleDefinition => new ModuleDefinition { Name = "HtmlText", - Description = "Renders HTML or Text", + Description = "Renders HTML or Text Content", Version = "1.0.0", - ServerAssemblyName = "Oqtane.Server" + ServerManagerType = "Oqtane.Modules.HtmlText.Manager.HtmlTextManager, Oqtane.Server" }; } } diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index 75336548..a3d15e8c 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -32,7 +32,7 @@ actions = new List(); actions.Add(new ActionViewModel { Action = "settings", Name = "Manage Settings" }); - if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerAssemblyName != "") + if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "") { actions.Add(new ActionViewModel { Action = "import", Name = "Import Content" }); actions.Add(new ActionViewModel { Action = "export", Name = "Export Content" }); diff --git a/Oqtane.Server/Controllers/ModuleDefinitionController.cs b/Oqtane.Server/Controllers/ModuleDefinitionController.cs index 9fc4f66e..b197e62d 100644 --- a/Oqtane.Server/Controllers/ModuleDefinitionController.cs +++ b/Oqtane.Server/Controllers/ModuleDefinitionController.cs @@ -104,52 +104,53 @@ namespace Oqtane.Controllers ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionId == id).FirstOrDefault(); if (moduledefinition != null) { - if (!string.IsNullOrEmpty(moduledefinition.ServerAssemblyName)) - { - string uninstallScript = ""; - Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(a => a.GetName().Name == moduledefinition.ServerAssemblyName); - if (assembly != null) - { - Stream resourceStream = assembly.GetManifestResourceStream(moduledefinition.ServerAssemblyName + ".Scripts.Uninstall.sql"); - if (resourceStream != null) - { - using (var reader = new StreamReader(resourceStream)) - { - uninstallScript = reader.ReadToEnd(); - } - } - } + // server assembly name should follow client naming convention + string assemblyname = Utilities.GetAssemblyName(moduledefinition.ModuleDefinitionName).Replace(".Client",".Server"); - foreach (Tenant tenant in _tenants.GetTenants()) + string uninstallScript = ""; + Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(a => a.GetName().Name == assemblyname); + if (assembly != null) + { + Stream resourceStream = assembly.GetManifestResourceStream(assemblyname + ".Scripts.Uninstall.sql"); + if (resourceStream != null) { - // uninstall module database schema - if (!string.IsNullOrEmpty(uninstallScript)) + using (var reader = new StreamReader(resourceStream)) { - _sql.ExecuteScript(tenant, uninstallScript); - _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Uninstall Script Executed For {ServerAssemblyName}", moduledefinition.ServerAssemblyName); + uninstallScript = reader.ReadToEnd(); } - // clean up module schema versions - _sql.ExecuteNonQuery(tenant, "DELETE FROM [dbo].[SchemaVersions] WHERE ScriptName LIKE '" + moduledefinition.ServerAssemblyName + "%'"); - _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Schema Versions Removed For {ServerAssemblyName}", moduledefinition.ServerAssemblyName); } } - string moduledefinitionname = moduledefinition.ModuleDefinitionName.Substring(0, moduledefinition.ModuleDefinitionName.IndexOf(",")); + foreach (Tenant tenant in _tenants.GetTenants()) + { + // uninstall module database schema + if (!string.IsNullOrEmpty(uninstallScript)) + { + _sql.ExecuteScript(tenant, uninstallScript); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Uninstall Script Executed For {AssemblyName}", assemblyname); + } + // clean up module schema versions + _sql.ExecuteNonQuery(tenant, "DELETE FROM [dbo].[SchemaVersions] WHERE ScriptName LIKE '" + assemblyname + "%'"); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Schema Versions Removed For {AssemblyName}", assemblyname); + } + + // format root assembly name + assemblyname = assemblyname.Replace(".Server", ""); // clean up module static resource folder - string folder = Path.Combine(_environment.WebRootPath, "Modules\\" + moduledefinitionname); + string folder = Path.Combine(_environment.WebRootPath, "Modules\\" + assemblyname); if (Directory.Exists(folder)) { Directory.Delete(folder, true); - _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Static Resources Removed For {ModuleDefinitionName}", moduledefinitionname); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Static Resources Removed For {AssemblynName}", assemblyname); } // remove module assembly from /bin string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - foreach (string file in Directory.EnumerateFiles(binfolder, moduledefinitionname + "*.*")) + foreach (string file in Directory.EnumerateFiles(binfolder, assemblyname + "*.*")) { System.IO.File.Delete(file); - _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Assemblies Removed For {ModuleDefinitionName}", moduledefinitionname); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Assembly Removed {Filename}", file); } // remove module definition @@ -194,13 +195,13 @@ namespace Oqtane.Controllers { rootPath = rootFolder.FullName + "\\"; moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, Oqtane.Client"; - moduleDefinition.ServerAssemblyName = "Oqtane.Server"; + moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server"; } else { rootPath = rootFolder.Parent.FullName + "\\" + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module\\"; - moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module.Client"; - moduleDefinition.ServerAssemblyName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module.Server"; + moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module.Client"; + moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module.Server"; } ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition); @@ -241,7 +242,7 @@ namespace Oqtane.Controllers text = text.Replace("[Description]", moduleDefinition.Description); text = text.Replace("[RootPath]", rootPath); text = text.Replace("[RootFolder]", rootFolder); - text = text.Replace("[ServerAssemblyName]", moduleDefinition.ServerAssemblyName); + text = text.Replace("[ServerManagerType]", moduleDefinition.ServerManagerType); text = text.Replace("[Folder]", folderPath); text = text.Replace("[File]", Path.GetFileName(filePath)); text = text.Replace("[FrameworkVersion]", Constants.Version); diff --git a/Oqtane.Server/Repository/ModuleRepository.cs b/Oqtane.Server/Repository/ModuleRepository.cs index 18d9df3b..7d88f0a1 100644 --- a/Oqtane.Server/Repository/ModuleRepository.cs +++ b/Oqtane.Server/Repository/ModuleRepository.cs @@ -83,21 +83,13 @@ namespace Oqtane.Repository modulecontent.Version = moduledefinition.Version; modulecontent.Content = ""; - if (moduledefinition.ServerAssemblyName != "") + if (moduledefinition.ServerManagerType != "") { - Assembly assembly = AppDomain.CurrentDomain.GetAssemblies() - .Where(item => item.FullName.StartsWith(moduledefinition.ServerAssemblyName)).FirstOrDefault(); - if (assembly != null) + Type moduletype = Type.GetType(moduledefinition.ServerManagerType); + if (moduletype != null && moduletype.GetInterface("IPortable") != null) { - Type moduletype = assembly.GetTypes() - .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(moduledefinition.ModuleDefinitionName.Substring(0, moduledefinition.ModuleDefinitionName.IndexOf(",")))) - .Where(item => item.GetInterfaces().Contains(typeof(IPortable))).FirstOrDefault(); - if (moduletype != null) - { - var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); - modulecontent.Content = ((IPortable)moduleobject).ExportModule(module); - } + var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); + modulecontent.Content = ((IPortable)moduleobject).ExportModule(module); } } content = JsonSerializer.Serialize(modulecontent); @@ -126,22 +118,14 @@ namespace Oqtane.Repository ModuleContent modulecontent = JsonSerializer.Deserialize(content); if (modulecontent.ModuleDefinitionName == moduledefinition.ModuleDefinitionName) { - if (moduledefinition.ServerAssemblyName != "") + if (moduledefinition.ServerManagerType != "") { - Assembly assembly = AppDomain.CurrentDomain.GetAssemblies() - .Where(item => item.FullName.StartsWith(moduledefinition.ServerAssemblyName)).FirstOrDefault(); - if (assembly != null) + Type moduletype = Type.GetType(moduledefinition.ServerManagerType); + if (moduletype != null && moduletype.GetInterface("IPortable") != null) { - Type moduletype = assembly.GetTypes() - .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(moduledefinition.ModuleDefinitionName.Substring(0, moduledefinition.ModuleDefinitionName.IndexOf(",")))) - .Where(item => item.GetInterfaces().Contains(typeof(IPortable))).FirstOrDefault(); - if (moduletype != null) - { - var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); + var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); ((IPortable)moduleobject).ImportModule(module, modulecontent.Content, modulecontent.Version); success = true; - } } } } diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 107893c3..4cba5e20 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -670,21 +670,13 @@ namespace Oqtane.Repository }; module = _moduleRepository.AddModule(module); - if (pagetemplatemodule.Content != "" && moduledefinition.ServerAssemblyName != "") + if (pagetemplatemodule.Content != "" && moduledefinition.ServerManagerType!= "") { - Assembly assembly = AppDomain.CurrentDomain.GetAssemblies() - .Where(item => item.FullName.StartsWith(moduledefinition.ServerAssemblyName)).FirstOrDefault(); - if (assembly != null) + Type moduletype = Type.GetType(moduledefinition.ServerManagerType); + if (moduletype != null && moduletype.GetInterface("IPortable") != null) { - Type moduletype = assembly.GetTypes() - .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(moduledefinition.ModuleDefinitionName.Substring(0, moduledefinition.ModuleDefinitionName.IndexOf(",")))) - .Where(item => item.GetInterfaces().Contains(typeof(IPortable))).FirstOrDefault(); - if (moduletype != null) - { - var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); + var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); ((IPortable) moduleobject).ImportModule(module, pagetemplatemodule.Content, moduledefinition.Version); - } } } diff --git a/Oqtane.Shared/Models/ModuleDefinition.cs b/Oqtane.Shared/Models/ModuleDefinition.cs index fe39b8e6..4832a5e2 100644 --- a/Oqtane.Shared/Models/ModuleDefinition.cs +++ b/Oqtane.Shared/Models/ModuleDefinition.cs @@ -17,7 +17,7 @@ namespace Oqtane.Models License = ""; Dependencies = ""; PermissionNames = ""; - ServerAssemblyName = ""; + ServerManagerType = ""; ControlTypeRoutes = ""; Template = ""; } @@ -53,7 +53,7 @@ namespace Oqtane.Models [NotMapped] public string PermissionNames { get; set; } [NotMapped] - public string ServerAssemblyName { get; set; } + public string ServerManagerType { get; set; } [NotMapped] public string ControlTypeRoutes { get; set; } [NotMapped] diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index fe8e8844..662d524d 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -74,6 +74,19 @@ namespace Oqtane.Shared } } + public static string GetAssemblyName(string fullyqualifiedtypename) + { + fullyqualifiedtypename = GetFullTypeName(fullyqualifiedtypename); + if (fullyqualifiedtypename.Contains(",")) + { + return fullyqualifiedtypename.Substring(fullyqualifiedtypename.IndexOf(",") + 1).Trim(); + } + else + { + return ""; + } + } + public static string GetTypeNameLastSegment(string typename, int segment) { if (typename.Contains(","))