diff --git a/docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md b/docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md new file mode 100644 index 0000000000..5ec8eb6c65 --- /dev/null +++ b/docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md @@ -0,0 +1,8 @@ +# ABP Version 7.4 Migration Guide + +This document is a guide for upgrading ABP v7.3 solutions to ABP v7.4. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application. + +## TemplateDefinition + +The `LocalizationResource(Type)` of `TemplateDefinition` class is changed to `LocalizationResourceName(string)`. + diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs index ba87dfb4ae..43cc829010 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs @@ -29,7 +29,7 @@ public class AbpTemplateRenderer : ITemplateRenderer, ITransientDependency string cultureName = null, Dictionary globalContext = null) { - var templateDefinition = TemplateDefinitionManager.Get(templateName); + var templateDefinition = await TemplateDefinitionManager.GetAsync(templateName); var renderEngine = templateDefinition.RenderEngine; diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs index 3c98daa22b..28b2e28ad0 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs @@ -12,10 +12,13 @@ public class AbpTextTemplatingOptions public string DefaultRenderingEngine { get; set; } + public HashSet DeletedTemplates { get; } + public AbpTextTemplatingOptions() { DefinitionProviders = new TypeList(); ContentContributors = new TypeList(); RenderingEngines = new Dictionary(); + DeletedTemplates = new HashSet(); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IDynamicTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IDynamicTemplateDefinitionStore.cs new file mode 100644 index 0000000000..e275eb39be --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IDynamicTemplateDefinitionStore.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating; + +public interface IDynamicTemplateDefinitionStore +{ + Task GetAsync([NotNull] string name); + + Task> GetAllAsync(); + + Task GetOrNullAsync(string name); +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IStaticTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IStaticTemplateDefinitionStore.cs new file mode 100644 index 0000000000..d298a42541 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IStaticTemplateDefinitionStore.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating; + +public interface IStaticTemplateDefinitionStore +{ + Task GetAsync([NotNull] string name); + + Task> GetAllAsync(); + + Task GetOrNullAsync(string name); +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs index 31af5d1da5..fa20673cea 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs @@ -1,16 +1,17 @@ using System.Collections.Generic; +using System.Threading.Tasks; using JetBrains.Annotations; namespace Volo.Abp.TextTemplating; public interface ITemplateDefinitionManager { - [NotNull] - TemplateDefinition Get([NotNull] string name); + [ItemNotNull] + Task GetAsync([NotNull] string name); - [NotNull] - IReadOnlyList GetAll(); + [ItemNotNull] + Task> GetAllAsync(); - [CanBeNull] - TemplateDefinition GetOrNull(string name); + [ItemCanBeNull] + Task GetOrNullAsync(string name); } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/NullIDynamicTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/NullIDynamicTemplateDefinitionStore.cs new file mode 100644 index 0000000000..326b525c0e --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/NullIDynamicTemplateDefinitionStore.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating; + +public class NullIDynamicTemplateDefinitionStore : IDynamicTemplateDefinitionStore, ISingletonDependency +{ + private readonly static Task CachedTemplateResult = Task.FromResult((TemplateDefinition)null); + + private readonly static Task> CachedFeaturesResult = Task.FromResult((IReadOnlyList)Array.Empty().ToImmutableList()); + + public Task GetAsync(string name) + { + return CachedTemplateResult; + } + + public Task> GetAllAsync() + { + return CachedFeaturesResult; + } + + public Task GetOrNullAsync(string name) + { + return CachedTemplateResult; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/StaticTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/StaticTemplateDefinitionStore.cs new file mode 100644 index 0000000000..d12db86da8 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/StaticTemplateDefinitionStore.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating; + +public class StaticTemplateDefinitionStore : IStaticTemplateDefinitionStore, ISingletonDependency +{ + protected Lazy> TemplateDefinitions { get; } + + protected AbpTextTemplatingOptions Options { get; } + + protected IServiceProvider ServiceProvider { get; } + + public StaticTemplateDefinitionStore(IOptions options, IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + Options = options.Value; + + TemplateDefinitions = new Lazy>(CreateTextTemplateDefinitions, true); + } + + public virtual Task GetAsync(string name) + { + Check.NotNull(name, nameof(name)); + + var template = GetOrNullAsync(name); + + if (template == null) + { + throw new AbpException("Undefined template: " + name); + } + + return template; + } + + public virtual Task> GetAllAsync() + { + return Task.FromResult>(TemplateDefinitions.Value.Values.ToImmutableList()); + } + + public virtual Task GetOrNullAsync(string name) + { + return Task.FromResult(TemplateDefinitions.Value.GetOrDefault(name)); + } + + protected virtual IDictionary CreateTextTemplateDefinitions() + { + var templates = new Dictionary(); + + using (var scope = ServiceProvider.CreateScope()) + { + var providers = Options + .DefinitionProviders + .Select(p => scope.ServiceProvider.GetRequiredService(p) as ITemplateDefinitionProvider) + .ToList(); + + var context = new TemplateDefinitionContext(templates); + + foreach (var provider in providers) + { + provider.PreDefine(context); + } + + foreach (var provider in providers) + { + provider.Define(context); + } + + foreach (var provider in providers) + { + provider.PostDefine(context); + } + } + + return templates; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs index 58ffcc491f..64ecd1f4c7 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs @@ -26,14 +26,14 @@ public class TemplateContentProvider : ITemplateContentProvider, ITransientDepen _templateDefinitionManager = templateDefinitionManager; } - public virtual Task GetContentOrNullAsync( + public virtual async Task GetContentOrNullAsync( [NotNull] string templateName, [CanBeNull] string cultureName = null, bool tryDefaults = true, bool useCurrentCultureIfCultureNameIsNull = true) { - var template = _templateDefinitionManager.Get(templateName); - return GetContentOrNullAsync(template, cultureName); + var template = await _templateDefinitionManager.GetAsync(templateName); + return await GetContentOrNullAsync(template, cultureName); } public virtual async Task GetContentOrNullAsync( diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs index d028f46702..64aeba815e 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs @@ -28,7 +28,7 @@ public class TemplateDefinition : IHasNameWithLocalizableDisplayName public string Layout { get; set; } [CanBeNull] - public Type LocalizationResource { get; set; } + public string LocalizationResourceName { get; set; } public bool IsInlineLocalized { get; set; } @@ -60,14 +60,26 @@ public class TemplateDefinition : IHasNameWithLocalizableDisplayName public TemplateDefinition( [NotNull] string name, - [CanBeNull] Type localizationResource = null, + [NotNull] Type localizationResource, + [CanBeNull] ILocalizableString displayName = null, + bool isLayout = false, + string layout = null, + string defaultCultureName = null) + : this(name, LocalizationResourceNameAttribute.GetName(localizationResource), displayName, isLayout, layout, defaultCultureName) + { + + } + + public TemplateDefinition( + [NotNull] string name, + [CanBeNull] string localizationResourceName = null, [CanBeNull] ILocalizableString displayName = null, bool isLayout = false, string layout = null, string defaultCultureName = null) { Name = Check.NotNullOrWhiteSpace(name, nameof(name), MaxNameLength); - LocalizationResource = localizationResource; + LocalizationResourceName = localizationResourceName; DisplayName = displayName ?? new FixedLocalizableString(Name); IsLayout = isLayout; Layout = layout; diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs index a282b5e5e2..7e2920e446 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs @@ -1,85 +1,50 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; +using System.Threading.Tasks; using Volo.Abp.DependencyInjection; namespace Volo.Abp.TextTemplating; public class TemplateDefinitionManager : ITemplateDefinitionManager, ISingletonDependency { - protected Lazy> TemplateDefinitions { get; } + protected readonly IStaticTemplateDefinitionStore StaticStore; + protected readonly IDynamicTemplateDefinitionStore DynamicStore; - protected AbpTextTemplatingOptions Options { get; } - - protected IServiceProvider ServiceProvider { get; } - - public TemplateDefinitionManager( - IOptions options, - IServiceProvider serviceProvider) + public TemplateDefinitionManager(IStaticTemplateDefinitionStore staticStore, IDynamicTemplateDefinitionStore dynamicStore) { - ServiceProvider = serviceProvider; - Options = options.Value; - - TemplateDefinitions = - new Lazy>(CreateTextTemplateDefinitions, true); + StaticStore = staticStore; + DynamicStore = dynamicStore; } - public virtual TemplateDefinition Get(string name) + public virtual async Task GetAsync(string name) { - Check.NotNull(name, nameof(name)); - - var template = GetOrNull(name); - - if (template == null) + var permission = await GetOrNullAsync(name); + if (permission == null) { - throw new AbpException("Undefined template: " + name); + throw new AbpException("Undefined Template: " + name); } - return template; + return permission; } - public virtual IReadOnlyList GetAll() + public virtual async Task GetOrNullAsync(string name) { - return TemplateDefinitions.Value.Values.ToImmutableList(); - } + Check.NotNull(name, nameof(name)); - public virtual TemplateDefinition GetOrNull(string name) - { - return TemplateDefinitions.Value.GetOrDefault(name); + return await StaticStore.GetOrNullAsync(name) ?? await DynamicStore.GetOrNullAsync(name); } - protected virtual IDictionary CreateTextTemplateDefinitions() + public virtual async Task> GetAllAsync() { - var templates = new Dictionary(); - - using (var scope = ServiceProvider.CreateScope()) - { - var providers = Options - .DefinitionProviders - .Select(p => scope.ServiceProvider.GetRequiredService(p) as ITemplateDefinitionProvider) - .ToList(); - - var context = new TemplateDefinitionContext(templates); + var staticTemplates = await StaticStore.GetAllAsync(); + var staticTemplateNames = staticTemplates + .Select(p => p.Name) + .ToImmutableHashSet(); - foreach (var provider in providers) - { - provider.PreDefine(context); - } - - foreach (var provider in providers) - { - provider.Define(context); - } - - foreach (var provider in providers) - { - provider.PostDefine(context); - } - } + var dynamicTemplates = await DynamicStore.GetAllAsync(); - return templates; + /* We prefer static Templates over dynamics */ + return staticTemplates.Concat(dynamicTemplates.Where(d => !staticTemplateNames.Contains(d.Name))).ToImmutableList(); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs index f496a8fea8..a2c354801d 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs @@ -31,9 +31,9 @@ public abstract class TemplateRenderingEngineBase : ITemplateRenderingEngine protected virtual IStringLocalizer GetLocalizerOrNull(TemplateDefinition templateDefinition) { - if (templateDefinition.LocalizationResource != null) + if (templateDefinition.LocalizationResourceName != null) { - return StringLocalizerFactory.Create(templateDefinition.LocalizationResource); + return StringLocalizerFactory.CreateByResourceName(templateDefinition.LocalizationResourceName); } return StringLocalizerFactory.CreateDefaultOrNull(); diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs index 0ae297a136..27e400c082 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs @@ -5,10 +5,12 @@ namespace Volo.Abp.TextTemplating.VirtualFiles; public class FileInfoLocalizedTemplateContentReader : ILocalizedTemplateContentReader { + private IFileInfo _fileInfo; private string _content; public async Task ReadContentsAsync(IFileInfo fileInfo) { + _fileInfo = fileInfo; _content = await fileInfo.ReadAsStringAsync(); } @@ -21,4 +23,13 @@ public class FileInfoLocalizedTemplateContentReader : ILocalizedTemplateContentR return null; } + + public TemplateContentFileInfo GetFile() + { + return new TemplateContentFileInfo() + { + FileName = _fileInfo.Name, + FileContent = _content + }; + } } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileInfo.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileInfo.cs new file mode 100644 index 0000000000..5469700432 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileInfo.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.TextTemplating.VirtualFiles; + +public class TemplateContentFileInfo +{ + public string FileName { get; set; } + + public string FileContent { get; set; } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileProvider.cs new file mode 100644 index 0000000000..0b049b07ab --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileProvider.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.VirtualFileSystem; + +namespace Volo.Abp.TextTemplating.VirtualFiles; + +public class TemplateContentFileProvider : ITransientDependency +{ + protected IVirtualFileProvider VirtualFileProvider { get; } + + public TemplateContentFileProvider(IVirtualFileProvider virtualFileProvider) + { + VirtualFileProvider = virtualFileProvider; + } + + public async Task> GetFilesAsync(TemplateDefinition templateDefinition) + { + var files = new List(); + + var virtualPath = templateDefinition.GetVirtualFilePathOrNull(); + if (virtualPath == null) + { + return files; + } + + var fileInfo = VirtualFileProvider.GetFileInfo(virtualPath); + if (!fileInfo.Exists) + { + var directoryContents = VirtualFileProvider.GetDirectoryContents(virtualPath); + if (!directoryContents.Exists) + { + throw new AbpException("Could not find a file/folder at the location: " + virtualPath); + } + + fileInfo = new VirtualDirectoryFileInfo(virtualPath, virtualPath, DateTimeOffset.UtcNow); + } + + if (fileInfo.IsDirectory) + { + //TODO: Configure file extensions. + var folderReader = new VirtualFolderLocalizedTemplateContentReader(new[] { ".tpl", ".cshtml" }); + await folderReader.ReadContentsAsync(VirtualFileProvider, virtualPath); + files.AddRange(folderReader.GetFiles()); + } + else + { + var singleFileReader = new FileInfoLocalizedTemplateContentReader(); + await singleFileReader.ReadContentsAsync(fileInfo); + files.Add(singleFileReader.GetFile()); + } + + return files; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs index 6ff24e4801..828978b1d2 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.FileProviders; using Volo.Abp.VirtualFileSystem; @@ -8,7 +9,7 @@ namespace Volo.Abp.TextTemplating.VirtualFiles; public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateContentReader { - private Dictionary _dictionary; + private Dictionary _dictionary; private readonly string[] _fileExtension; public VirtualFolderLocalizedTemplateContentReader(string[] fileExtension) @@ -20,7 +21,7 @@ public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateCon IVirtualFileProvider virtualFileProvider, string virtualPath) { - _dictionary = new Dictionary(); + _dictionary = new Dictionary(); var directoryContents = virtualFileProvider.GetDirectoryContents(virtualPath); if (!directoryContents.Exists) @@ -35,7 +36,11 @@ public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateCon continue; } - _dictionary.Add(file.Name.RemovePostFix(_fileExtension), await file.ReadAsStringAsync()); + _dictionary.Add(file.Name.RemovePostFix(_fileExtension), new TemplateContentFileInfo() + { + FileName = file.Name, + FileContent = await file.ReadAsStringAsync() + }); } } @@ -46,6 +51,11 @@ public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateCon return null; } - return _dictionary.GetOrDefault(cultureName); + return _dictionary.GetOrDefault(cultureName)?.FileContent; + } + + public List GetFiles() + { + return _dictionary.Values.ToList(); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs index 10312e1513..109547ada5 100644 --- a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs @@ -45,6 +45,11 @@ public class DefaultAbpCompiledViewProvider : IAbpCompiledViewProvider, ITransie } var templateContent = await _templateContentProvider.GetContentOrNullAsync(templateDefinition); + if (templateContent == null) + { + throw new AbpException($"Razor template content of {templateDefinition.Name} is null!"); + } + return CachedAssembles.GetOrAdd((templateDefinition.Name + templateContent).ToMd5(), await CreateAssembly(templateContent)); } diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs index 582ebaf907..86298f2daf 100644 --- a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs @@ -74,7 +74,7 @@ public class RazorTemplateRenderingEngine : TemplateRenderingEngineBase, ITransi Dictionary globalContext, object model = null) { - var templateDefinition = TemplateDefinitionManager.Get(templateName); + var templateDefinition = await TemplateDefinitionManager.GetAsync(templateName); var renderedContent = await RenderSingleTemplateAsync( templateDefinition, diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs index 4612ec04df..a4da669893 100644 --- a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs @@ -61,7 +61,7 @@ public class ScribanTemplateRenderingEngine : TemplateRenderingEngineBase, ITran Dictionary globalContext, object model = null) { - var templateDefinition = TemplateDefinitionManager.Get(templateName); + var templateDefinition = await TemplateDefinitionManager.GetAsync(templateName); var renderedContent = await RenderSingleTemplateAsync( templateDefinition, diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs index 6a0edcb3f5..fada3effe7 100644 --- a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs @@ -38,7 +38,7 @@ public class AbpCompiledViewProviderOptions_Tests : TemplateDefinitionTests +{ + [Fact] + public async Task GetRazorFilesAsync() + { + var definition = await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail); + var files = await TemplateContentFileProvider.GetFilesAsync(definition); + files.Count.ShouldBe(2); + files.ShouldContain(x => x.FileName == "en.cshtml" && x.FileContent.Contains("Welcome @Model.Name to the abp.io!")); + files.ShouldContain(x => x.FileName == "tr.cshtml" && x.FileContent.Contains("Merhaba @Model.Name, abp.io'ya hoşgeldiniz!")); + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ScribanTemplateContentFileProvider_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ScribanTemplateContentFileProvider_Tests.cs new file mode 100644 index 0000000000..674173313c --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ScribanTemplateContentFileProvider_Tests.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.TextTemplating.VirtualFiles; +using Xunit; + +namespace Volo.Abp.TextTemplating.Scriban.SampleTemplates; + +public class ScribanTemplateContentFileProvider_Tests : TemplateContentFileProvider_Tests +{ + [Fact] + public async Task GetScribanFilesAsync() + { + var definition = await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail); + var files = await TemplateContentFileProvider.GetFilesAsync(definition); + files.Count.ShouldBe(2); + files.ShouldContain(x => x.FileName == "en.tpl" && x.FileContent.Contains("Welcome {{model.name}} to the abp.io!")); + files.ShouldContain(x => x.FileName == "tr.tpl" && x.FileContent.Contains("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!")); + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs index 036080cc26..02ce27d2b7 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs @@ -1,4 +1,5 @@ -using Shouldly; +using System.Threading.Tasks; +using Shouldly; using Volo.Abp.Modularity; using Xunit; @@ -15,28 +16,28 @@ public abstract class TemplateDefinitionTests : AbpTextTemplatin } [Fact] - public void Should_Retrieve_Template_Definition_By_Name() + public async Task Should_Retrieve_Template_Definition_By_Name() { - var welcomeEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail); + var welcomeEmailTemplate = await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail); welcomeEmailTemplate.Name.ShouldBe(TestTemplates.WelcomeEmail); welcomeEmailTemplate.IsInlineLocalized.ShouldBeFalse(); - var forgotPasswordEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail); + var forgotPasswordEmailTemplate = await TemplateDefinitionManager.GetAsync(TestTemplates.ForgotPasswordEmail); forgotPasswordEmailTemplate.Name.ShouldBe(TestTemplates.ForgotPasswordEmail); forgotPasswordEmailTemplate.IsInlineLocalized.ShouldBeTrue(); } [Fact] - public void Should_Get_Null_If_Template_Not_Found() + public async Task Should_Get_Null_If_Template_Not_Found() { - var definition = TemplateDefinitionManager.GetOrNull("undefined-template"); + var definition = await TemplateDefinitionManager.GetOrNullAsync("undefined-template"); definition.ShouldBeNull(); } [Fact] - public void Should_Retrieve_All_Template_Definitions() + public async Task Should_Retrieve_All_Template_Definitions() { - var definitions = TemplateDefinitionManager.GetAll(); + var definitions = await TemplateDefinitionManager.GetAllAsync(); definitions.Count.ShouldBeGreaterThan(1); } } diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs index 7ba1850d9c..aee41db4be 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs @@ -24,7 +24,7 @@ public abstract class LocalizedTemplateContentReaderFactory_Tests : AbpTextTemplatingTestBase + where TStartupModule : IAbpModule +{ + protected readonly TemplateContentFileProvider TemplateContentFileProvider; + protected readonly ITemplateDefinitionManager TemplateDefinitionManager; + + protected TemplateContentFileProvider_Tests() + { + TemplateContentFileProvider = GetRequiredService(); + TemplateDefinitionManager = GetRequiredService(); + } + + [Fact] + public async Task GetFilesAsync() + { + var definition = await TemplateDefinitionManager.GetAsync(TestTemplates.HybridTemplateScriban); + + var files = await TemplateContentFileProvider.GetFilesAsync(definition); + files.Count.ShouldBe(1); + files.ShouldContain(x => x.FileName == "TestScribanTemplate.tpl" && x.FileContent == "Hello {{model.name}}, {{L \"HowAreYou\" }}"); + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs index 89dc93051c..f2f0cdafef 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs @@ -24,13 +24,13 @@ public abstract class VirtualFileTemplateContributor_Tests : Abp public async Task Should_Get_Localized_Content_By_Culture() { (await VirtualFileTemplateContentContributor.GetOrNullAsync( - new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail), + new TemplateContentContributorContext(await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail), ServiceProvider, "en"))) .ShouldBe(WelcomeEmailEnglishContent); (await VirtualFileTemplateContentContributor.GetOrNullAsync( - new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail), + new TemplateContentContributorContext(await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail), ServiceProvider, "tr"))) .ShouldBe(WelcomeEmailTurkishContent); @@ -41,7 +41,7 @@ public abstract class VirtualFileTemplateContributor_Tests : Abp { (await VirtualFileTemplateContentContributor.GetOrNullAsync( new TemplateContentContributorContext( - TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail), + await TemplateDefinitionManager.GetAsync(TestTemplates.ForgotPasswordEmail), ServiceProvider, null))) .ShouldBe(ForgotPasswordEmailEnglishContent); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs index 5b90574e59..e02d671652 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpApplicationManager.cs @@ -44,8 +44,8 @@ public class AbpApplicationManager : OpenIddictApplicationManager(); + _testData = ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task Populate_Descriptor_With_Application_Test() + { + var app1 = (await _applicationManager.FindByClientIdAsync(_testData.App1ClientId)).As(); + + var descriptor = new AbpApplicationDescriptor(); + await _applicationManager.PopulateAsync(descriptor, app1); + + app1.ClientUri.ShouldNotBeNull(); + app1.LogoUri.ShouldNotBeNull(); + + descriptor.ClientUri.ShouldBe(app1.ClientUri); + descriptor.LogoUri.ShouldBe(app1.LogoUri); + } + + [Fact] + public async Task Populate_Application_With_Descriptor_Test() + { + var app1 = (await _applicationManager.FindByClientIdAsync(_testData.App1ClientId)).As(); + + var descriptor = new AbpApplicationDescriptor() + { + ClientUri = "https://new.com", + LogoUri = "https://new.com/logo.png" + }; + await _applicationManager.PopulateAsync(app1, descriptor); + + app1.ClientUri.ShouldBe(descriptor.ClientUri); + app1.LogoUri.ShouldBe(descriptor.LogoUri); + } +} diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs index eccdf828c6..df8a88a9d3 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/Volo/Abp/OpenIddict/OpenIddictDataSeedContributor.cs @@ -92,7 +92,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep private async Task CreateApplicationsAsync() { - await _applicationManager.CreateAsync(await GetOpenIddictApplicationModelAsync(_testData.App1Id, new OpenIddictApplicationDescriptor + await _applicationManager.CreateAsync(await GetOpenIddictApplicationModelAsync(_testData.App1Id, new AbpApplicationDescriptor { ClientId = _testData.App1ClientId, ConsentType = OpenIddictConstants.ConsentTypes.Explicit, @@ -137,10 +137,12 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Prefixes.Scope + _testData.Scope1Name - } + }, + ClientUri = "https://abp.io/TestApplication", + LogoUri = "https://abp.io/TestApplication.png" })); - await _applicationManager.CreateAsync(await GetOpenIddictApplicationModelAsync(_testData.App2Id, new OpenIddictApplicationDescriptor + await _applicationManager.CreateAsync(await GetOpenIddictApplicationModelAsync(_testData.App2Id, new AbpApplicationDescriptor { ClientId = _testData.App2ClientId, ConsentType = OpenIddictConstants.ConsentTypes.Explicit, @@ -186,7 +188,9 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep OpenIddictConstants.Permissions.Prefixes.Scope + _testData.Scope1Name, OpenIddictConstants.Permissions.Prefixes.Scope + _testData.Scope2Name, - } + }, + ClientUri = "https://abp.io/TestApplication2", + LogoUri = "https://abp.io/TestApplication2.png" })); } @@ -240,7 +244,6 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep Subject = "TestSubject1", Type = OpenIddictConstants.AuthorizationTypes.Permanent, CreationDate = _clock.Now - })); await _authorizationManager.CreateAsync(await GetOpenIddictAuthorizationModelAsync(_testData.Authorization2Id, new OpenIddictAuthorizationDescriptor diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs index 6726069d0d..a7e9c7eb2c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs @@ -15,7 +15,7 @@ public class MyProjectNameEFCoreDbSchemaMigrator : ITransientDependency public async Task MigrateAsync() { - /* We intentionally resolving the MyProjectNameDbContext + /* We intentionally resolve the MyProjectNameDbContext * from IServiceProvider (instead of directly injecting it) * to properly get the connection string of the current tenant in the * current scope. diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs index 6726069d0d..a7e9c7eb2c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Data/MyProjectNameEFCoreDbSchemaMigrator.cs @@ -15,7 +15,7 @@ public class MyProjectNameEFCoreDbSchemaMigrator : ITransientDependency public async Task MigrateAsync() { - /* We intentionally resolving the MyProjectNameDbContext + /* We intentionally resolve the MyProjectNameDbContext * from IServiceProvider (instead of directly injecting it) * to properly get the connection string of the current tenant in the * current scope. diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Data/MyProjectNameEFCoreDbSchemaMigrator.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Data/MyProjectNameEFCoreDbSchemaMigrator.cs index 6726069d0d..a7e9c7eb2c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Data/MyProjectNameEFCoreDbSchemaMigrator.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Data/MyProjectNameEFCoreDbSchemaMigrator.cs @@ -15,7 +15,7 @@ public class MyProjectNameEFCoreDbSchemaMigrator : ITransientDependency public async Task MigrateAsync() { - /* We intentionally resolving the MyProjectNameDbContext + /* We intentionally resolve the MyProjectNameDbContext * from IServiceProvider (instead of directly injecting it) * to properly get the connection string of the current tenant in the * current scope. diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Data/MyProjectNameEFCoreDbSchemaMigrator.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Data/MyProjectNameEFCoreDbSchemaMigrator.cs index 6726069d0d..a7e9c7eb2c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Data/MyProjectNameEFCoreDbSchemaMigrator.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Data/MyProjectNameEFCoreDbSchemaMigrator.cs @@ -15,7 +15,7 @@ public class MyProjectNameEFCoreDbSchemaMigrator : ITransientDependency public async Task MigrateAsync() { - /* We intentionally resolving the MyProjectNameDbContext + /* We intentionally resolve the MyProjectNameDbContext * from IServiceProvider (instead of directly injecting it) * to properly get the connection string of the current tenant in the * current scope. diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreMyProjectNameDbSchemaMigrator.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreMyProjectNameDbSchemaMigrator.cs index 10b3d75c3d..f4b87fbd57 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreMyProjectNameDbSchemaMigrator.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreMyProjectNameDbSchemaMigrator.cs @@ -20,7 +20,7 @@ public class EntityFrameworkCoreMyProjectNameDbSchemaMigrator public async Task MigrateAsync() { - /* We intentionally resolving the MyProjectNameDbContext + /* We intentionally resolve the MyProjectNameDbContext * from IServiceProvider (instead of directly injecting it) * to properly get the connection string of the current tenant in the * current scope.