From 0e8c3a9623ffdd4dcb11f0147cea631af6112161 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 27 May 2026 16:11:39 +0330 Subject: [PATCH] last ... --- .../Entities/XStringEntityConfiguration.cs | 5 +- ...aseStringResourceProviderControllerBase.cs | 387 +++++++++++ .../XStringRepositoryControllerBase.cs | 33 + ...XStringRepositoryProviderControllerBase.cs | 37 ++ Controllers/XStringServiceControllerBase.cs | 34 + .../XStringServiceProviderControllerBase.cs | 38 ++ DI/XDIHelperExtension.cs | 3 + ...aseStringResourceProviderControllerBase.cs | 111 ++++ ...ngEvents.cs => XStringRepositoryEvents.cs} | 0 Providers/Entities/XStringSeederBase.cs | 24 + Providers/XStringEntityRegisterar.cs | 30 + README.md | 615 +++++++++++++++++- 12 files changed, 1315 insertions(+), 2 deletions(-) create mode 100644 Controllers/XBaseStringResourceProviderControllerBase.cs create mode 100644 Controllers/XStringRepositoryControllerBase.cs create mode 100644 Controllers/XStringRepositoryProviderControllerBase.cs create mode 100644 Controllers/XStringServiceControllerBase.cs create mode 100644 Controllers/XStringServiceProviderControllerBase.cs create mode 100644 Interfaces/IXBaseStringResourceProviderControllerBase.cs rename Providers/Entities/{XStringEvents.cs => XStringRepositoryEvents.cs} (100%) create mode 100644 Providers/Entities/XStringSeederBase.cs create mode 100644 Providers/XStringEntityRegisterar.cs diff --git a/Configurations/Entities/XStringEntityConfiguration.cs b/Configurations/Entities/XStringEntityConfiguration.cs index f5f5f7f..b02c17e 100644 --- a/Configurations/Entities/XStringEntityConfiguration.cs +++ b/Configurations/Entities/XStringEntityConfiguration.cs @@ -1,3 +1,4 @@ +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using xDataService.Providers; using xStringService.Models.Entities; @@ -7,6 +8,8 @@ namespace xStringService.Configurations.Entities public class XStringEntityConfiguration : XBaseEntityTypeConfiguration { public override void Configure(EntityTypeBuilder builder) - { } + { + builder.ToTable("Strings"); + } } } \ No newline at end of file diff --git a/Controllers/XBaseStringResourceProviderControllerBase.cs b/Controllers/XBaseStringResourceProviderControllerBase.cs new file mode 100644 index 0000000..07b3875 --- /dev/null +++ b/Controllers/XBaseStringResourceProviderControllerBase.cs @@ -0,0 +1,387 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using xCommons.Configurations; +using xCommons.Extensions; +using xCommons.Providers; +using xExceptions.Constants; +using xIdentityService.Controllers; +using xIdentityService.Interfaces; +using xModels.Base; +using xModels.Dtos; +using xStringService.Interfaces; +using xStringService.Models.Dtos; + +namespace xStringService.Controllers +{ + /// + /// an Implementation of Base Actions of a Controller which Provides + /// XString Resource Service Actions ... + /// + public abstract class XBaseStringResourceProviderControllerBase : XBaseIdentityApiV1Controller, IXBaseStringResourceProviderControllerBase + { + private readonly IXBaseStringResourceProvider resourceProvider; + + protected XBaseStringResourceProviderControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXBaseStringResourceProvider resourceProvider + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider + ) + { + this.resourceProvider = resourceProvider; + } + + /// + /// Add Specified Locales ... + /// + /// + /// + /// + /// + [HttpPost("Add")] + public virtual async Task>> Add( + [FromQuery] string suffix, + [FromBody] XBaseRangeRequest locales, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(suffix) + .AddNotNull(locales) + .AddNotZeroChilds(locales.Items) + .ValidateGroupAsync(); + + // + var connectionId = GetConnectionId(); + + // + var result = await resourceProvider.Add( + suffix: suffix, + locales: locales.Items, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Add or Update Specified Locales ... + /// + /// + /// + /// + /// + [HttpPost("AddOrUpdate")] + public virtual async Task>> AddOrUpdate( + [FromQuery] string resource, + [FromBody] XBaseRangeRequest locales, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(resource) + .AddNotNull(locales) + .AddNotZeroChilds(locales.Items) + .ValidateGroupAsync(); + + // + var connectionId = GetConnectionId(); + + // + var result = await resourceProvider.AddOrUpdate( + resource: resource, + locales: locales.Items, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Add Specified Resource ... + /// + /// + /// + /// + /// + [HttpPost("AddResource")] + public virtual async Task> AddResource( + [FromQuery] string suffix, + [FromBody] XResourceDto item, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(suffix) + .AddNotNull(item) + .AddNotZeroChilds(item.Locales) + .ValidateGroupAsync(); + + // + var connectionId = GetConnectionId(); + + // + var result = await resourceProvider.AddResource( + item: item, + suffix: suffix, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Get Specified Locale ... + /// + /// + /// + /// + /// + [HttpGet("GetLocale")] + public virtual async Task> GetLocale( + [FromQuery] string suffix, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(suffix) + .ValidateGroupAsync(); + + // + var result = await resourceProvider.GetLocale( + suffix: suffix, + language: language, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Get Resources of Specified Resource Title ... + /// + /// + /// + /// + [HttpGet("GetResource")] + public virtual async Task> GetResource( + [FromQuery] string suffix, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(suffix) + .ValidateGroupAsync(); + + // + var result = await resourceProvider.GetResource( + suffix: suffix, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Remove all Resources which belongs to Specified Suffix ... + /// + /// + /// + /// + [HttpDelete("Remove")] + public virtual async Task Remove( + [FromQuery] string suffix, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(suffix) + .ValidateGroupAsync(); + + // + var connectionId = GetConnectionId(); + + // + await resourceProvider.Remove( + suffix: suffix, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Remove Specified Resource ... + /// + /// + /// + /// + /// + [HttpDelete("RemoveResource")] + public virtual async Task Remove( + [FromQuery] string resource, + [FromQuery] string language, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(resource) + .AddNotEmpty(language) + .ValidateGroupAsync(); + + // + var connectionId = GetConnectionId(); + + // + await resourceProvider.Remove( + resource: resource, + language: language, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + } +} \ No newline at end of file diff --git a/Controllers/XStringRepositoryControllerBase.cs b/Controllers/XStringRepositoryControllerBase.cs new file mode 100644 index 0000000..d9e75aa --- /dev/null +++ b/Controllers/XStringRepositoryControllerBase.cs @@ -0,0 +1,33 @@ +using System; +using System.Linq; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.Extensions.Logging; +using xCommons.Configurations; +using xCommons.Providers; +using xDataService.Controllers; +using xDataService.Interfaces; +using xStringService.Interfaces.Entities; +using xStringService.Models.Entities; + +namespace xStringService.Controllers +{ + public abstract class XStringRepositoryControllerBase : XBaseRepositoryController, IXBaseRepositoryController + { + protected XStringRepositoryControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + XValidationProvider validationProvider, + IXStringRepository repository, + Func, IOrderedQueryable> defaultOrderBuilder = null, + Func, IIncludableQueryable> defaultIncludeBuilder = null + ) : base( + logger, + appConfiguration, + validationProvider, + repository, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { } + } +} \ No newline at end of file diff --git a/Controllers/XStringRepositoryProviderControllerBase.cs b/Controllers/XStringRepositoryProviderControllerBase.cs new file mode 100644 index 0000000..49d3d9d --- /dev/null +++ b/Controllers/XStringRepositoryProviderControllerBase.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.Extensions.Logging; +using xCommons.Configurations; +using xCommons.Providers; +using xIdentityService.Interfaces; +using xPushService.Controllers; +using xPushService.Interfaces; +using xStringService.Interfaces.Entities; +using xStringService.Models.Entities; +using xStringService.Providers.Entities; + +namespace xStringService.Controllers +{ + public abstract class XStringRepositoryProviderControllerBase : XBaseRepositoryProviderController, IXBaseRepositoryProviderController + { + protected XStringRepositoryProviderControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXStringRepositoryProvider provider, + Func, IOrderedQueryable> defaultOrderBuilder = null, + Func, IIncludableQueryable> defaultIncludeBuilder = null + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + provider, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { } + } +} \ No newline at end of file diff --git a/Controllers/XStringServiceControllerBase.cs b/Controllers/XStringServiceControllerBase.cs new file mode 100644 index 0000000..8f6be7a --- /dev/null +++ b/Controllers/XStringServiceControllerBase.cs @@ -0,0 +1,34 @@ +using System; +using System.Linq; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.Extensions.Logging; +using xCommons.Configurations; +using xCommons.Providers; +using xDataService.Controllers; +using xDataService.Interfaces; +using xStringService.Interfaces.Dtos; +using xStringService.Models.Dtos; +using xStringService.Models.Entities; + +namespace xStringService.Controllers +{ + public abstract class XStringServiceControllerBase : XBaseServiceController, IXBaseServiceController + { + protected XStringServiceControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + XValidationProvider validationProvider, + IXStringRepositoryService repositoryService, + Func, IOrderedQueryable> defaultOrderBuilder = null, + Func, IIncludableQueryable> defaultIncludeBuilder = null + ) : base( + logger, + appConfiguration, + validationProvider, + repositoryService, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { } + } +} \ No newline at end of file diff --git a/Controllers/XStringServiceProviderControllerBase.cs b/Controllers/XStringServiceProviderControllerBase.cs new file mode 100644 index 0000000..d2deeb4 --- /dev/null +++ b/Controllers/XStringServiceProviderControllerBase.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.Extensions.Logging; +using xCommons.Configurations; +using xCommons.Providers; +using xIdentityService.Interfaces; +using xPushService.Controllers; +using xPushService.Interfaces; +using xStringService.Interfaces.Dtos; +using xStringService.Models.Dtos; +using xStringService.Models.Entities; +using xStringService.Providers.Dtos; + +namespace xStringService.Controllers +{ + public abstract class XStringServiceProviderControllerBase : XBaseServiceProviderController, IXBaseServiceProviderController + { + protected XStringServiceProviderControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXStringServiceProvider provider, + Func, IOrderedQueryable> defaultOrderBuilder = null, + Func, IIncludableQueryable> defaultIncludeBuilder = null + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + provider, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { } + } +} \ No newline at end of file diff --git a/DI/XDIHelperExtension.cs b/DI/XDIHelperExtension.cs index e454303..cb1eb57 100644 --- a/DI/XDIHelperExtension.cs +++ b/DI/XDIHelperExtension.cs @@ -168,6 +168,8 @@ namespace xStringService.DI } // + // Maske Instance of Repository Descriptor + // Based on Provided Type ... switch(repositoryType) { // @@ -193,6 +195,7 @@ namespace xStringService.DI } // + // Register XString Repository Descriptor ... services.AddXRepository( lifeTime: lifeTime, descriptor: descriptor diff --git a/Interfaces/IXBaseStringResourceProviderControllerBase.cs b/Interfaces/IXBaseStringResourceProviderControllerBase.cs new file mode 100644 index 0000000..b8ab67f --- /dev/null +++ b/Interfaces/IXBaseStringResourceProviderControllerBase.cs @@ -0,0 +1,111 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using xModels.Base; +using xModels.Dtos; +using xStringService.Models.Dtos; + +namespace xStringService.Interfaces +{ + /// + /// an Interface which Described Base Actions of a Controller which Provides + /// XString Resource Service Actions ... + /// + public interface IXBaseStringResourceProviderControllerBase + { + /// + /// Add Specified Locales ... + /// + /// + /// + /// + /// + [HttpPost("Add")] + Task>> Add( + [FromQuery] string suffix, + [FromBody] XBaseRangeRequest locales, + CancellationToken cancellationToken = default + ); + + /// + /// Add or Update Specified Locales ... + /// + /// + /// + /// + /// + [HttpPost("AddOrUpdate")] + Task>> AddOrUpdate( + [FromQuery] string resource, + [FromBody] XBaseRangeRequest locales, + CancellationToken cancellationToken = default + ); + + /// + /// Add Specified Resource ... + /// + /// + /// + /// + /// + [HttpPost("AddResource")] + Task> AddResource( + [FromQuery] string suffix, + [FromBody] XResourceDto item, + CancellationToken cancellationToken = default + ); + + /// + /// Get Specified Locale ... + /// + /// + /// + /// + /// + [HttpGet("GetLocale")] + Task> GetLocale( + [FromQuery] string suffix, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ); + + /// + /// Get Resources of Specified Resource Title ... + /// + /// + /// + /// + [HttpGet("GetResource")] + Task> GetResource( + [FromQuery] string suffix, + CancellationToken cancellationToken = default + ); + + /// + /// Remove all Resources which belongs to Specified Suffix ... + /// + /// + /// + /// + [HttpDelete("Remove")] + Task Remove( + [FromQuery] string suffix, + CancellationToken cancellationToken = default + ); + + /// + /// Remove Specified Resource ... + /// + /// + /// + /// + /// + [HttpDelete("RemoveResource")] + Task Remove( + [FromQuery] string resource, + [FromQuery] string language, + CancellationToken cancellationToken = default + ); + } +} \ No newline at end of file diff --git a/Providers/Entities/XStringEvents.cs b/Providers/Entities/XStringRepositoryEvents.cs similarity index 100% rename from Providers/Entities/XStringEvents.cs rename to Providers/Entities/XStringRepositoryEvents.cs diff --git a/Providers/Entities/XStringSeederBase.cs b/Providers/Entities/XStringSeederBase.cs new file mode 100644 index 0000000..a401f2c --- /dev/null +++ b/Providers/Entities/XStringSeederBase.cs @@ -0,0 +1,24 @@ +using xDataService.Configuration; +using xDataService.Interfaces; +using xDataService.Providers; +using xStringService.Interfaces; +using xStringService.Models.Entities; + +namespace xStringService.Providers.Entities +{ + public abstract class XStringSeederBase : XBaseDbSeeder, IXStringSeeder + { + protected XStringSeederBase( + string entity, + string database, + IXBaseRepository repository, + XDataServiceConfiguration dataServiceConfiguration + ) : base( + entity, + database, + repository, + dataServiceConfiguration + ) + { } + } +} \ No newline at end of file diff --git a/Providers/XStringEntityRegisterar.cs b/Providers/XStringEntityRegisterar.cs new file mode 100644 index 0000000..c82eb7c --- /dev/null +++ b/Providers/XStringEntityRegisterar.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore; +using xDataService.Interfaces; +using xDataService.Providers; +using xStringService.Models.Entities; + +namespace xStringService.Providers +{ + /// + /// an Entity Registerar class for XStringService ... + /// + public class XStringEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar + { + public XStringEntityRegisterar() + : base(nameof(XStringEntityRegisterar)) + { + // + // Add XString Entity ... + AddEntity(); + } + + /// + /// Configure Entities ... + /// + /// + public override void ConfigureEntities(ModelBuilder modelBuilder) + { + base.ConfigureEntities(modelBuilder); + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index a0fb2c3..378e671 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,619 @@ # xStringService -it is a Part of xDashboard on SaherElm IT Center which provides String Resources Futures ... +it is a Part of xDashboard on SaherElm IT Center which provides: + +- all requirements to Implement String Resource Features in a **xDashboard** based Project. + +this module has following dependencies : + +- xModels +- xCommons +- xDataService +- xPushService +- xIdentityModels +- xIdentityService + +for configure and use this Module refer to DI.XDIHelperExtension.cs file. + +## String Resource + +an string resource is a Key/Value based structure which used in Multi Language Applications for accessing Translated of Spcified Values by Key, in Specified Languages. +this architecture is very useful for implementing other services in an Application. such as Terms and Conditions. + +## Data Persists + +all of Provided features of this Module is works based on Data Persistance. so data models is Very Important. +in this section all Data models explained. + +data manipulation done using **xDataService** provided Features. + +- **XString**: an Entity Model for Mapping to Tables. +- **XStringDto**: a Data Transfer Object for Representing a Data Model. +- **XStringEntityConfiguration**: a Configuration file for XString Entity. +- **XStringEntityHub**: a Hub Implementation for XString Entity Model. +- **XStringDtoHub**: a Hub Implementation for XStringDto Model. +- **XStringEntityRegisterar**: an Implementation class for Dynamically Register XString Entity in a DbContext. +- **IXStringRepositoryEvents**: an Interface for Repository Events Describing of XString Entity. +- **XStringRepositoryEvents**: an Implementation for Repository Events of XString Entity. +- **IXStringKeyGenerator**: an Interface for Describing Key Generator Actions for XString Entity. +- **XStringKeyGenerator**: an Implementation for Describing Key Generator Actions for XString Entity. +- **IXStringRepository**: an Interface for Describing XString Repository Actions. +- **XStringEFRepository**: an Implementation of EF Core based XString Repository Actions. +- **XStringMongoRepository**: an Implementation of MongoDb based XString Repository Actions. +- **XStringMongoRepository**: an Implementation of MongoDb based XString Repository Actions. +- **XStringInMemoryRepository**: an Implementation of InMemory based XString Repository Actions. +- **IXStringSeeder**: an Interface for Describe XString DbSeeder actions. +- **XStringSeederBase**: an abstraction of Implementation of XString DbSeeder actions. +- **IXStringRepositoryProvider**: an Interface for Describing XString Repository Provider (using Hubs) actions. +- **XStringRepositoryProvider**: an Implementation of XString Repository Provider (using Hubs) actions. +- **IXStringRepositoryService**: an Interface for Describing XString Repository Service Actions (using XStringDto). +- **XStringRepositoryService**: an Implementation of XString Repository Service Actions (using XStringDto). +- **IXStringServiceProvider**: an Interface for Describing XString Repository Service Actions Provider (using Hubs and XStringDto). +- **XStringServiceProvider**: an Implementation of XString Repository Service Actions Provider (using Hubs and XStringDto). +- **XStringGraphType**: introduce XString Data model for GraphQL using. +- **XStringGraphQuery**: introduce Repositry Implementation of XString model actions as Query Actions for GraphQL using. +- **XStringGraphSchema**: introduce XString Query Schema for GraphQL using. +- **IXStringGraphQLTypeHelper**: an Interface for Describing XString GraphQL Type Helper Provided Actions. +- **IXStringGraphQLTypeHelper**: an Implementation of XString GraphQL Type Helper Provided Actions. + +data presistance almost is a Down Layer works which handled using Service it self. +but in some Used cases of Applications Business Logics, for Manipulating resources you can use above Registered Services by Injecting them. + +## Providers + +this module actually used to act as a base Provider for implementing Features based on it. +for this purpose, provides some Features which described in this section. + +### String Resource Provider + +some services used XString model for Provide Specially Concept's of Actions. for example Terms and Conditions Services use XString Persisted Resource for Specified Purpose. + +this Module provides some sort of tools for this purpose. which described in this section. + +#### Data Transfer Models + +this service used some Data Transfer Models for Data Providing. which Described in this section. + +```C# +public class XLocaleResourceDto : XBaseDto +{ + public string Language { get; set; } + public string Value { get; set; } +} + +public class XResourceDto : XBaseDto +{ + public string Resource { get; set; } + public IEnumerable Locales { get; set; } = new HashSet(); +} +``` + +#### IXBaseStringResourceProvider + +an interface for Describe Provided Actions of Resource based Service. + +```C# +/// +/// a Base Class for Handling Resources Based on Specified Types on +/// String Resources Use ... +/// such as: +/// - Terms and Conditions; +/// - Contents; +/// - News; +/// - etc ... +/// +public interface IXBaseStringResourceProvider +{ + // + #region Props ... + string Prefix { get; } + IXStringServiceProvider Provider { get; } + XAppConfiguration AppConfiguration { get; } + #endregion + + // + #region Actions ... + /// + /// Prepare Resource Title by Given Data ... + /// + /// + /// + string GetResourceTitle(string suffix); + + /// + /// Add Specified Locales ... + /// + /// + /// + /// + /// + /// + Task> Add( + string suffix, + IEnumerable locales, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// Add Or Update Specified Locals ... + /// + /// + /// + /// + /// + /// + Task> AddOrUpdate( + string resource, + IEnumerable locales, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// Get Specified Locale ... + /// + /// + /// + /// + /// + Task GetLocale( + string suffix, + string language = null, + CancellationToken cancellationToken = default + ); + + /// + /// Add Specified Resource ... + /// + /// + /// + /// + /// + /// + Task AddResource( + string suffix, + XResourceDto item, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// Get Resources of Specified Resource ... + /// + /// + /// + /// + Task GetResource( + string suffix, + CancellationToken cancellationToken = default + ); + + /// + /// Remove Specified Suffix Resources ... + /// + /// + /// + /// + /// + Task Remove( + string suffix, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// Remove Specified Resource ... + /// + /// + /// + /// + /// + /// + Task Remove( + string resource, + string language, + string connectionId = null, + CancellationToken cancellationToken = default + ); + #endregion +} +``` + +#### XBaseStringResourceProvider + +an implementation of Provided Actions of Resource based Service. + +```C# +/// +/// a Base Class for Handling Resources Based on Specified Types on +/// String Resources Use ... +/// such as: +/// - Terms and Conditions; +/// - Contents; +/// - News; +/// - etc ... +/// +public abstract class XBaseStringResourceProvider : IXBaseStringResourceProvider +{ + // + #region Props ... + public string Prefix { get; } + public IXStringServiceProvider Provider { get; } + public XAppConfiguration AppConfiguration { get; } + #endregion + + // + #region Constructor ... + public XBaseStringResourceProvider( + string prefix, + IXStringServiceProvider provider, + XAppConfiguration appConfiguration + ) + { + // + Prefix = prefix; + Provider = provider; + AppConfiguration = appConfiguration; + } + #endregion + + // + #region Actions ... + /// + /// Prepare Resource Title by Given Data ... + /// + /// + /// + public string GetResourceTitle(string suffix) + { + // + string result = ""; + + // + if (suffix.IsNullOrEmpty()) + { + return result; + } + + // + result = $"{Prefix}_${suffix}"; + + // + return result; + } + + /// + /// Add Specified Locales ... + /// + /// + /// + /// + /// + /// + public async Task> Add( + string suffix, + IEnumerable locales, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + // Validate ... + var has = + locales.HasChild() && + !suffix.IsNullOrEmpty(); + if (!has) + { + XException.InvalidArgs.Throw(); + } + + // + // Prepare Resource ID ... + string resourceID = GetResourceTitle(suffix); + var result = await locales.SelectAsync(async l => + { + // + // Normalize Language ... + if (l.Language.IsNullOrEmpty()) + { + l.Language = AppConfiguration.DefaultLanguage; + } + + // + // Prepare Model for Add ... + var model = new XStringDto + { + Language = l.Language, + TranslatedValue = l.Value, + ResourceTitle = resourceID, + }; + model = await Provider.AddAsync( + item: model, + saveChanges: true, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + return model; + }); + + // + return result; + } + + /// + /// Add Or Update Specified Locals ... + /// + /// + /// + /// + /// + /// + public async Task> AddOrUpdate( + string resource, + IEnumerable locales, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + // Validate ... + bool isValid = + locales.HasChild() && + !resource.IsNullOrEmpty() && + locales.All(l => !l.Value.IsNullOrEmpty() && !l.Language.IsNullOrEmpty()); + if (!isValid) + { + XException.InvalidArgs.Throw(); + } + + // + // Check Resource ... + isValid = resource.Contains(Prefix); + if (!isValid) + { + XException.NotAllowed.Throw(); + } + + // + var result = await locales.SelectAsync(async l => + await Provider.AddOrUpdateByLocaleResource( + item: l, + resource: resource, + connectionId: connectionId, + cancellationToken: cancellationToken + ) + ); + + // + return result; + } + + /// + /// Get Specified Locale ... + /// + /// + /// + /// + /// + public async Task GetLocale( + string suffix, + string language = null, + CancellationToken cancellationToken = default + ) + { + // + // Normalize ... + if (language.IsNullOrEmpty()) + { + language = AppConfiguration.DefaultLanguage; + } + + // + // Validate ... + if (suffix.IsNullOrEmpty() || language.IsNullOrEmpty()) + { + XException.InvalidArgs.Throw(); + } + + // + // Prepare Resource Title ... + string resource = GetResourceTitle(suffix); + + // + // Check Resource Exists ... + var isExists = await Provider.IsResourceExists( + resource: resource, + language: language, + cancellationToken: cancellationToken + ); + if (!isExists) + { + XException.NotFound.Throw(); + } + + // + // Retrieve and Validate Dto Model ... + var model = await Provider.Get( + resource: resource, + language: language, + cancellationToken: cancellationToken + ); + if (model.IsNullOrDefault()) + { + XException.ActionFailed.Throw(); + } + + // + // Prepare Result ... + var result = model + .ToXLocaleResourceDto(); + return result; + } + + /// + /// Add Specified Resource ... + /// + /// + /// + /// + /// + /// + public async Task AddResource( + string suffix, + XResourceDto item, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + // Validate ... + if (suffix.IsNullOrEmpty() || + item.IsNull() || + !item.Locales.HasChild() || + !item.Locales.All(l => !l.Value.IsNullOrEmpty())) + { + XException.InvalidArgs.Throw(); + } + + // + // Prepare Resource ID ... + var addedLocals = await Add( + suffix: suffix, + locales: item.Locales, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + if (!addedLocals.HasChild()) + { + XException.ActionFailed.Throw(); + } + + // + var result = await GetResource( + suffix: suffix, + cancellationToken: cancellationToken + ); + return result; + } + + /// + /// Get Resources of Specified Resource ... + /// + /// + /// + /// + public async Task GetResource( + string suffix, + CancellationToken cancellationToken = default + ) + { + // + // Validate ... + if (suffix.IsNullOrEmpty()) + { + XException.InvalidArgs.Throw(); + } + + // + // Prepare Resource ID ... + string resourceID = GetResourceTitle(suffix); + + // + // Prepare ... + var result = await Provider.GetResource( + resource: resourceID, + cancellationToken: cancellationToken + ); + return result; + } + + /// + /// Remove Specified Suffix Resources ... + /// + /// + /// + /// + /// + public async Task Remove( + string suffix, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + // Validate ... + if (suffix.IsNullOrEmpty()) + { + XException.InvalidArgs.Throw(); + } + + // + var resourceID = GetResourceTitle(suffix); + await Provider.RemoveResource( + resource: resourceID, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + } + + /// + /// Remove Specified Resource ... + /// + /// + /// + /// + /// + /// + public async Task Remove( + string resource, + string language, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + // Validate ... + bool isValid = + !resource.IsNullOrEmpty() && + !language.IsNullOrEmpty(); + if (!isValid) + { + XException.InvalidArgs.Throw(); + } + + // + // Check resource ID Contains Prefix ... + isValid = resource.Contains(Prefix); + if (!isValid) + { + XException.NotAllowed.Throw(); + } + + // + // Check Exists ... + var isExists = await Provider.IsResourceExists( + resource: resource, + language: language, + cancellationToken: cancellationToken + ); + if (!isExists) + { + XException.NotFound.Throw(); + } + + // + // Remove Resource ... + await Provider.Remove( + resource: resource, + language: language, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + } + #endregion +} +``` ## Maintainer