diff --git a/DigitalData.Core.API/ControllerExtensions.cs b/DigitalData.Core.API/ControllerExtensions.cs
index 7e02ea3..4009711 100644
--- a/DigitalData.Core.API/ControllerExtensions.cs
+++ b/DigitalData.Core.API/ControllerExtensions.cs
@@ -1,4 +1,5 @@
using DigitalData.Core.Contracts.Application;
+using DigitalData.Core.DTO;
using Microsoft.AspNetCore.Mvc;
using System.Text;
@@ -50,10 +51,8 @@ namespace DigitalData.Core.API
/// Returns an ObjectResult representing an internal server error (status code 500) with optional exception and message details.
///
/// The ControllerBase instance representing the controller.
- /// Optional. The exception that occurred, if any.
- /// Optional. A custom error message to include in the response.
- /// /// Optional. A custom error message key to include in the response.
+ /// Optional. A custom error resul to include in the response.
/// An ObjectResult representing an internal server error (status code 500).
- public static ObjectResult InnerServiceError(this ControllerBase controllerBase, IServiceMessage? serviceMessage = null) => controllerBase.StatusCode(500, serviceMessage);
+ public static ObjectResult InnerServiceError(this ControllerBase controllerBase, Result? result = null) => controllerBase.StatusCode(500, result);
}
}
\ No newline at end of file
diff --git a/DigitalData.Core.API/DigitalData.Core.API.csproj b/DigitalData.Core.API/DigitalData.Core.API.csproj
index 97b79bd..5cd5d03 100644
--- a/DigitalData.Core.API/DigitalData.Core.API.csproj
+++ b/DigitalData.Core.API/DigitalData.Core.API.csproj
@@ -13,6 +13,7 @@
+
diff --git a/DigitalData.Core.API/LocalizationExtensions.cs b/DigitalData.Core.API/LocalizationExtensions.cs
index 49befb9..20f548f 100644
--- a/DigitalData.Core.API/LocalizationExtensions.cs
+++ b/DigitalData.Core.API/LocalizationExtensions.cs
@@ -20,10 +20,10 @@ namespace DigitalData.Core.API
public static IServiceCollection AddCookieBasedLocalizer(this IServiceCollection services, string resourcesPath)
{
// Adds localization services with the specified resources path.
- services.AddLocalization(options => options.ResourcesPath = resourcesPath);
+ services.AddLocalization(options => options.ResourcesPath = resourcesPath)
// Adds MVC services with view localization and data annotations localization.
- services.AddMvc().AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
+ .AddMvc().AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
return services;
diff --git a/DigitalData.Core.Application/CRUDService.cs b/DigitalData.Core.Application/CRUDService.cs
index ab9c290..70e04a8 100644
--- a/DigitalData.Core.Application/CRUDService.cs
+++ b/DigitalData.Core.Application/CRUDService.cs
@@ -4,6 +4,7 @@ using AutoMapper;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.Localization;
+using DigitalData.Core.DTO;
namespace DigitalData.Core.Application
{
@@ -15,26 +16,29 @@ namespace DigitalData.Core.Application
/// The DTO type for update operations.
/// The entity type.
/// The type of the identifier for the entity.
- public class CRUDService : ServiceBase, ICRUDService, IServiceBase
+ public class CRUDService : ICRUDService
where TCRUDRepository : ICRUDRepository where TCreateDto : class where TReadDto : class where TUpdateDto : class where TEntity : class
{
protected readonly TCRUDRepository _repository;
protected readonly IMapper _mapper;
protected readonly PropertyInfo? _keyPropertyInfo;
+ protected readonly IStringLocalizer _localizer;
///
/// Initializes a new instance of the CRUDService class with the specified repository, translation service, and mapper.
///
/// The CRUD repository for accessing the database.
- /// The service for translating messages based on culture.
+ /// The localizer for translating messages based on culture.
/// The AutoMapper instance for mapping between DTOs and entity objects.
- public CRUDService(TCRUDRepository repository, IStringLocalizer defaultLocalizer, IMapper mapper) : base(defaultLocalizer)
+ public CRUDService(TCRUDRepository repository, IStringLocalizer localizer, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
_keyPropertyInfo = typeof(TEntity).GetProperties()
.FirstOrDefault(prop => Attribute.IsDefined(prop, typeof(KeyAttribute)));
+
+ _localizer = localizer;
}
///
@@ -42,14 +46,11 @@ namespace DigitalData.Core.Application
///
/// The DTO to create an entity from.
/// A service result indicating success or failure, including the entity DTO.
- public virtual async Task> CreateAsync(TCreateDto createDto)
+ public virtual async Task> CreateAsync(TCreateDto createDto)
{
var entity = _mapper.MapOrThrow(createDto);
var createdEntity = await _repository.CreateAsync(entity);
- if (createdEntity is null)
- return Failed();
- else
- return Successful(KeyValueOf(createdEntity));
+ return createdEntity is null ? Result.Fail() : Result.Success(KeyValueOf(createdEntity));
}
///
@@ -57,27 +58,23 @@ namespace DigitalData.Core.Application
///
/// The identifier of the entity to read.
/// A service result indicating success or failure, including the read DTO if successful.
- public virtual async Task> ReadByIdAsync(TId id)
+ public virtual async Task> ReadByIdAsync(TId id)
{
var entity = await _repository.ReadByIdAsync(id);
- if (entity is null)
- {
- var translatedMessage = MessageKey.EntityDoesNotExist.LocalizedBy(_localizer);
- return Failed();
- }
- else
- return Successful(_mapper.MapOrThrow(entity));
+ return entity is null
+ ? Result.Fail().Message(_localizer[Key.EntityDoesNotExist])
+ : Result.Success(_mapper.MapOrThrow(entity));
}
///
/// Asynchronously reads all entities and maps them to read DTOs.
///
/// A service result including a collection of read DTOs.
- public virtual async Task>> ReadAllAsync()
+ public virtual async Task>> ReadAllAsync()
{
var entities = await _repository.ReadAllAsync();
var readDto = _mapper.MapOrThrow>(entities);
- return Successful(readDto);
+ return Result.Success(readDto);
}
///
@@ -85,17 +82,11 @@ namespace DigitalData.Core.Application
///
/// The DTO to update an entity from.
/// A service message indicating success or failure.
- public virtual async Task UpdateAsync(TUpdateDto updateDto)
+ public virtual async Task UpdateAsync(TUpdateDto updateDto)
{
var entity = _mapper.MapOrThrow(updateDto);
bool isUpdated = await _repository.UpdateAsync(entity);
- if (isUpdated)
- return Successful();
- else
- {
- var translatedMessage = MessageKey.UpdateFailed.LocalizedBy(_localizer);
- return Failed();
- }
+ return isUpdated ? Result.Success() : Result.Fail().Message(_localizer[Key.UpdateFailed]);
}
///
@@ -103,26 +94,15 @@ namespace DigitalData.Core.Application
///
/// The identifier of the entity to delete.
/// A service message indicating success or failure.
- public virtual async Task DeleteAsyncById(TId id)
+ public virtual async Task DeleteAsyncById(TId id)
{
TEntity? entity = await _repository.ReadByIdAsync(id);
if (entity is null)
- {
- var deletionFailedMessage = MessageKey.DeletionFailed.LocalizedBy(_localizer);
- var entityDoesNotExistMessage = MessageKey.EntityDoesNotExist.LocalizedBy(_localizer);
- return new ServiceMessage(isSuccess: false, deletionFailedMessage, entityDoesNotExistMessage);
- }
+ return Result.Fail().Message(_localizer[Key.DeletionFailed], _localizer[Key.EntityDoesNotExist]);
bool isDeleted = await _repository.DeleteAsync(entity);
-
- if (isDeleted)
- return Successful();
- else
- {
- var deletionFailedMessage = MessageKey.DeletionFailed.LocalizedBy(_localizer);
- return Failed(deletionFailedMessage);
- }
+ return isDeleted ? Result.Success() : Result.Fail().Message(_localizer[Key.DeletionFailed]);
}
///
diff --git a/DigitalData.Core.Application/DIExtensions.cs b/DigitalData.Core.Application/DIExtensions.cs
index 45078ce..2000121 100644
--- a/DigitalData.Core.Application/DIExtensions.cs
+++ b/DigitalData.Core.Application/DIExtensions.cs
@@ -1,5 +1,4 @@
using AutoMapper;
-using DigitalData.Core.Application.DTO;
using DigitalData.Core.Contracts.Application;
using DigitalData.Core.Contracts.Infrastructure;
using Microsoft.Extensions.Configuration;
@@ -66,30 +65,9 @@ namespace DigitalData.Core.Application
return service;
}
- public static IServiceCollection AddResponseService(this IServiceCollection service)
- {
- service.AddScoped();
- return service;
- }
-
public static IServiceCollection AddJWTService(this IServiceCollection services, Func tokenDescriptorFactory)
{
return services.AddScoped, JWTService>(provider => new (tokenDescriptorFactory));
}
-
- public static IServiceCollection AddCookieConsentSettings(this IServiceCollection services)
- {
- services.AddSingleton(sp =>
- {
- var configuration = sp.GetRequiredService();
- var settings = configuration.GetSection("CookieConsentSettings").Get();
- if (settings is null)
- {
- throw new ConfigurationErrorsException("The 'CookieConsentSettings' section is missing or improperly configured in appsettings.json.");
- }
- return settings;
- });
- return services;
- }
}
}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/DigitalData.Core.Application.csproj b/DigitalData.Core.Application/DigitalData.Core.Application.csproj
index c47f59a..f59d953 100644
--- a/DigitalData.Core.Application/DigitalData.Core.Application.csproj
+++ b/DigitalData.Core.Application/DigitalData.Core.Application.csproj
@@ -21,4 +21,8 @@
+
+
+
+
diff --git a/DigitalData.Core.Application/DirectorySearchService.cs b/DigitalData.Core.Application/DirectorySearchService.cs
index a45159c..8293a11 100644
--- a/DigitalData.Core.Application/DirectorySearchService.cs
+++ b/DigitalData.Core.Application/DirectorySearchService.cs
@@ -6,11 +6,12 @@ using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using System.DirectoryServices.AccountManagement;
using Microsoft.Extensions.Localization;
+using DigitalData.Core.DTO;
namespace DigitalData.Core.Application
{
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")]
- public class DirectorySearchService : ServiceBase, IDirectorySearchService
+ public class DirectorySearchService : IDirectorySearchService
{
private readonly IMemoryCache _memoryCache;
public string ServerName { get; }
@@ -18,8 +19,9 @@ namespace DigitalData.Core.Application
public string SearchRootPath { get; }
private readonly DateTimeOffset _userCacheExpiration;
public Dictionary CustomSearchFilters { get; }
+ protected readonly IStringLocalizer _localizer;
- public DirectorySearchService(IConfiguration configuration, ILogger logger, IMemoryCache memoryCache, IStringLocalizer defaultLocalizer) : base(defaultLocalizer)
+ public DirectorySearchService(IConfiguration configuration, ILogger logger, IMemoryCache memoryCache, IStringLocalizer localizer)
{
_memoryCache = memoryCache;
@@ -37,6 +39,8 @@ namespace DigitalData.Core.Application
_userCacheExpiration = default;
else
_userCacheExpiration = DateTimeOffset.Now.Date.AddDays(dayCounts);
+
+ _localizer = localizer;
}
public bool ValidateCredentials(string dirEntryUsername, string dirEntryPassword)
@@ -45,7 +49,7 @@ namespace DigitalData.Core.Application
return context.ValidateCredentials(dirEntryUsername, dirEntryPassword);
}
- public IServiceResult> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
+ public DataResult> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
{
List list = new();
@@ -71,17 +75,17 @@ namespace DigitalData.Core.Application
list.Add(rpc);
}
- return Successful>(list);
+ return Result.Success>(list);
}
- public IServiceResult> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
+ public DataResult> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
{
List list = new();
_memoryCache.TryGetValue(username, out DirectoryEntry? searchRoot);
if (searchRoot is null)
- return Failed>(MessageKey.DirSearcherDisconnected.ToString());
+ return Result.Fail>().Message(_localizer[Key.DirSearcherDisconnected]);
return FindAll(searchRoot, filter, searchScope, sizeLimit, properties);
}
diff --git a/DigitalData.Core.Application/EnumerableExtensoins.cs b/DigitalData.Core.Application/EnumerableExtensoins.cs
deleted file mode 100644
index e3863af..0000000
--- a/DigitalData.Core.Application/EnumerableExtensoins.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DigitalData.Core.Application
-{
- ///
- /// Provides extension methods for IEnumerable.
- ///
- public static class EnumerableExtensions
- {
- ///
- /// Concatenates the members of a collection, using the specified separator between each member.
- ///
- /// The type of the elements of the enumerable.
- /// The IEnumerable whose elements to concatenate.
- /// The string to use as a separator. Separator is included in the returned string only between elements of the collection.
- /// A string that consists of the elements in the collection delimited by the separator string. If the collection is empty, the method returns String.Empty.
- public static string Join(this IEnumerable enumerable, string separator = ". ") => string.Join(separator, enumerable);
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/Key.cs b/DigitalData.Core.Application/Key.cs
new file mode 100644
index 0000000..d8e352f
--- /dev/null
+++ b/DigitalData.Core.Application/Key.cs
@@ -0,0 +1,11 @@
+namespace DigitalData.Core.Application
+{
+ public static class Key
+ {
+ public static readonly string EntityDoesNotExist = "EntityDoesNotExist";
+ public static readonly string ReadFailed = "ReadFailed";
+ public static readonly string UpdateFailed = "UpdateFailed";
+ public static readonly string DeletionFailed = "DeletionFailed";
+ public static readonly string DirSearcherDisconnected = "DirSearcherDisconnected";
+ }
+}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/LoggerExtensions.cs b/DigitalData.Core.Application/LoggerExtensions.cs
deleted file mode 100644
index d18a435..0000000
--- a/DigitalData.Core.Application/LoggerExtensions.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using DigitalData.Core.Contracts.Application;
-using Microsoft.Extensions.Logging;
-
-namespace DigitalData.Core.Application
-{
- ///
- /// Provides extension methods for ILogger to handle logging of message collections and service messages more effectively.
- ///
- public static class LoggerExtensions
- {
- ///
- /// Logs a list of messages at the specified log level.
- ///
- /// The extended ILogger instance.
- /// The severity level of the log entry.
- /// The collection of messages to log.
- /// The separator used to join messages. Default is newline.
- /// Additional arguments used for formatting the log message.
- public static void LogMessageList(this ILogger logger, LogLevel logLevel, IEnumerable messages, string separator = "\n", params object?[] args)
- {
- if (messages.Any())
- logger.Log(logLevel: logLevel, message: string.Join(separator, messages), args);
- }
-
- ///
- /// Logs all messages from a service message instance, categorized by message type to appropriate log levels.
- ///
- /// The extended ILogger instance.
- /// The service message instance containing categorized messages.
- /// The separator used to join messages within each category. Default is newline.
- public static void LogServiceMessage(this ILogger logger, IServiceMessage serviceMessage, string separator = "\n")
- {
- logger.LogMessageList(LogLevel.Trace, serviceMessage.TraceMessages, separator);
- logger.LogMessageList(LogLevel.Debug, serviceMessage.DebugMessages, separator);
- logger.LogMessageList(LogLevel.Information, serviceMessage.InformationMessages, separator);
- logger.LogMessageList(LogLevel.Warning, serviceMessage.WarningMessages, separator);
- logger.LogMessageList(LogLevel.Error, serviceMessage.ErrorMessages, separator);
- logger.LogMessageList(LogLevel.Critical, serviceMessage.CriticalMessages, separator);
- }
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/MessageKey.cs b/DigitalData.Core.Application/MessageKey.cs
deleted file mode 100644
index 8fa7767..0000000
--- a/DigitalData.Core.Application/MessageKey.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DigitalData.Core.Application
-{
- public enum MessageKey
- {
- EntityDoesNotExist,
- ReadFailed,
- UpdateFailed,
- DeletionFailed,
- DirSearcherDisconnected
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/ResponseService.cs b/DigitalData.Core.Application/ResponseService.cs
deleted file mode 100644
index 4ccd1c9..0000000
--- a/DigitalData.Core.Application/ResponseService.cs
+++ /dev/null
@@ -1,211 +0,0 @@
-using DigitalData.Core.Contracts.Application;
-using Microsoft.Extensions.Localization;
-
-namespace DigitalData.Core.Application
-{
- public class ResponseService : IResponseService
- {
- protected readonly IStringLocalizer _localizer;
-
- public ResponseService(IStringLocalizer defaultLocalizer)
- {
- _localizer = defaultLocalizer;
- }
-
- #region WITHOUT_MESSAGE
-
- ///
- /// Creates a service message indicating success or failure without additional messages.
- ///
- /// Indicates if the operation was successful.
- /// A service message reflecting the operation outcome.
- public IServiceMessage CreateMessage(bool isSuccess = false) => new ServiceMessage()
- {
- IsSuccess = isSuccess
- };
-
- ///
- /// Creates a service result containing the provided data and a success flag, without additional messages.
- ///
- /// The type of the data included in the result.
- /// The data to include in the result.
- /// Indicates if the operation was successful.
- /// A service result with the specified data and outcome.
- public IServiceResult CreateResult(T? data = default, bool isSuccess = false) => new ServiceResult()
- {
- IsSuccess = isSuccess,
- Data = data
- };
-
- ///
- /// Creates a service message indicating a successful operation without additional messages.
- ///
- /// A service message indicating a successful operation.
- public IServiceMessage Successful() => CreateMessage(true);
-
- ///
- /// Creates a service message indicating a failed operation without additional messages.
- ///
- /// A service message indicating a failed operation.
- public IServiceMessage Failed() => CreateMessage(false);
-
- ///
- /// Creates a successful service result with the specified data, without additional messages.
- ///
- /// The type of data included in the result.
- /// The data to include in the result.
- /// A successful service result containing the specified data.
- public IServiceResult Successful(T data) => CreateResult(data, true);
-
- ///
- /// Creates a failed service result with optional data, without additional messages.
- ///
- /// The type of data the service result can contain.
- /// Optional data to include in the result.
- /// A failed service result, which may or may not contain the specified data.
- public IServiceResult Failed(T? data = default) => CreateResult(data, false);
-
- #endregion
- #region WITH_STRING_MESSAGE
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a service message with the specified success flag and messages.
- ///
- /// Indicates if the operation was successful.
- /// An array of messages associated with the operation.
- /// A new instance of reflecting the operation outcome.
- public virtual IServiceMessage CreateMessage(bool isSuccess, params string[] messages) => new ServiceMessage(isSuccess, messages);
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a service result containing the provided data, success flag, and messages.
- ///
- /// The type of the data included in the result.
- /// The data to include in the result.
- /// Indicates if the operation was successful.
- /// An array of messages associated with the operation.
- /// A new instance of with the specified data and outcome.
- public virtual IServiceResult CreateResult(T? data = default, bool isSuccess = true, params string[] messages) => new ServiceResult(data, isSuccess, messages);
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a successful service message.
- ///
- /// An array of success messages.
- /// A successful service message.
- public virtual IServiceMessage Successful(params string[] messages) => CreateMessage(true, messages);
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a failed service message.
- ///
- /// An array of failure messages.
- /// A failed service message.
- public virtual IServiceMessage Failed(params string[] messages) => CreateMessage(false, messages);
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a successful service result with the provided data.
- ///
- /// The type of data included in the result.
- /// The data to include in the result.
- /// An array of success messages.
- /// A successful service result containing the specified data.
- public virtual IServiceResult Successful(T data, params string[] messages) => CreateResult(data, true, messages);
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a failed service result, optionally including data.
- ///
- /// The type of data the service result can contain.
- /// Optional data to include in the failed result.
- /// An array of failure messages.
- /// A failed service result, which may or may not contain the specified data.
- public virtual IServiceResult Failed(T? data = default, params string[] messages) => CreateResult(data, false, messages);
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a failed service result using only failure messages, without explicitly including data.
- ///
- ///
- /// This method provides a convenient way to create a failed service result when the failure does not pertain to any specific data,
- /// or when the inclusion of data is not necessary to convey the failure reason. The data part of the result will be set to its default value.
- ///
- /// The type of data the service result can contain. The result will contain the default value for this type.
- /// An array of failure messages that provide details about the reasons for the operation's failure.
- /// A failed service result. The data part of the result will be set to the default value for the specified type,
- /// and it will include the provided failure messages.
- public virtual IServiceResult Failed(params string[] messages) => Failed(default, messages);
-
- #endregion
- #region WITH_ENUM_MESSAGE
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a service message with the specified success flag and enumeration messages.
- ///
- /// Indicates if the operation was successful.
- /// An array of enumeration values associated with the operation.
- /// A new instance of reflecting the operation outcome with enumeration messages.
- public IServiceMessage CreateMessage(bool isSuccess, params Enum[] messages) => CreateMessage(isSuccess, messages.Select(m => m.ToString()).ToArray());
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a service result containing the provided data, success flag, and enumeration messages.
- ///
- /// The type of the data included in the result.
- /// The data to include in the result.
- /// Indicates if the operation was successful.
- /// An array of enumeration values associated with the operation.
- /// A new instance of with the specified data and outcome using enumeration messages.
- public IServiceResult CreateResult(T? data, bool isSuccess, params Enum[] messages) => CreateResult(data, isSuccess, messages.Select(m => m.ToString()).ToArray());
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a successful service message using enumeration messages.
- ///
- /// An array of success enumeration values.
- /// A successful service message.
- public IServiceMessage Successful(params Enum[] messages) => CreateMessage(true, messages.Select(m => m.ToString()).ToArray());
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a failed service message using enumeration messages.
- ///
- /// An array of failure enumeration values.
- /// A failed service message.
- public IServiceMessage Failed(params Enum[] messages) => CreateMessage(false, messages.Select(m => m.ToString()).ToArray());
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a successful service result with the provided data using enumeration messages.
- ///
- /// The type of data included in the result.
- /// The data to include in the result.
- /// An array of success enumeration values.
- /// A successful service result containing the specified data.
- public IServiceResult Successful(T data, params Enum[] messages) => CreateResult(data, true, messages.Select(m => m.ToString()).ToArray());
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a failed service result, optionally including data, using enumeration messages.
- ///
- /// The type of data the service result can contain.
- /// Optional data to include in the failed result.
- /// An array of failure enumeration values.
- /// A failed service result, which may or may not contain the specified data.
- public IServiceResult Failed(T? data = default, params Enum[] messages) => CreateResult(data, false, messages.Select(m => m.ToString()).ToArray());
-
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ///
- /// Creates a failed service result using only failure messages, without explicitly including data.
- ///
- /// The type of data the service result can contain. The result will contain the default value for this type.
- /// An array of failure enumeration values that provide details about the reasons for the operation's failure.
- /// A failed service result. The data part of the result will be set to the default value for the specified type,
- /// and it will include the provided failure messages.
- public IServiceResult Failed(params Enum[] messages) => Failed(default(T), messages);
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/ServiceBase.cs b/DigitalData.Core.Application/ServiceBase.cs
deleted file mode 100644
index 73c8ca6..0000000
--- a/DigitalData.Core.Application/ServiceBase.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using AutoMapper;
-using DigitalData.Core.Contracts.Application;
-using Microsoft.Extensions.Localization;
-
-namespace DigitalData.Core.Application
-{
- ///
- /// Provides a base implementation of .
- ///
- public class ServiceBase : ResponseService, IServiceBase, IResponseService
- {
- public ServiceBase(IStringLocalizer defaultLocalizer) : base(defaultLocalizer)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/ServiceMessage.cs b/DigitalData.Core.Application/ServiceMessage.cs
deleted file mode 100644
index 96bedb1..0000000
--- a/DigitalData.Core.Application/ServiceMessage.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using DigitalData.Core.Contracts.Application;
-using System.Text.Json.Serialization;
-
-namespace DigitalData.Core.Application
-{
- ///
- /// Represents the outcome of a service operation, encapsulating the success or failure status,
- /// and any associated messages. It also supports optional translation of message keys for localization purposes.
- ///
- public class ServiceMessage : IServiceMessage
- {
- ///
- /// Initializes a new instance of the ServiceMessage class.
- ///
- public ServiceMessage()
- {
- }
-
- ///
- /// Initializes a new instance of the ServiceMessage class, specifying the success status.
- /// Optionally, a function for translating message keys can be provided.
- /// If a translation function is provided, it will be used for both string and enum message keys.
- ///
- /// Indicates whether the service operation was successful.
- /// If provided, it will also be adapted for translating enum keys by converting them to strings first.
- [Obsolete("Deprecated: initialize objects using object initializer.")]
- public ServiceMessage(bool isSuccess)
- {
- IsSuccess = isSuccess;
- }
-
- ///
- /// Initializes a new instance of the ServiceMessage class with specified success status, and messages.
- ///
- /// Indicates whether the service operation was successful.
- /// An array of messages related to the operation's outcome.
- [Obsolete("Deprecated: initialize objects using object initializer.")]
- public ServiceMessage(bool isSuccess, params string[] messages)
- {
- IsSuccess = isSuccess;
- Messages = messages.ToList();
- }
-
- ///
- /// Gets or sets a value indicating whether the service operation was successful.
- ///
- public bool IsSuccess { get; set; } = false;
-
- ///
- /// Represents the list of flags that indicate specific types of statuses or conditions in a service operation.
- /// These flags help in categorizing the state of the operation more granularly, allowing for multiple conditions to be represented simultaneously.
- ///
- [JsonIgnore]
- public ICollection Flags { get; } = new List();
-
- ///
- /// Checks if any of the current service message's flags matches the specified flag based on their string representations.
- /// This method is useful for conditional logic where the exact string representation of the flag values is crucial.
- ///
- /// The flag to check against the current service message's flags.
- /// true if a flag with a matching string representation exists; otherwise, false.
- public bool HasFlag(Enum flag) => Flags.Any(f => f.ToString() == flag.ToString());
-
- ///
- /// [Obsolete("Deprecated: Use ClientMessages instead.")]
- /// Gets a collection of messages associated with the service operation. These messages can be error descriptions,
- /// success notifications, or other relevant information related to the operation's outcome.
- ///
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- public ICollection Messages { get; init; } = new List();
-
- ///
- /// Gets a collection of messages intended for client display. This replaces the deprecated 'Messages' property.
- ///
- public ICollection ClientMessages { get; init; } = new List();
-
- ///
- /// Gets a collection of messages used for tracing program execution at a fine-grained level. These are typically voluminous and detailed.
- ///
- [JsonIgnore]
- public ICollection TraceMessages { get; init; } = new List();
-
- ///
- /// Gets a collection of messages helpful for debugging during development. These messages are often diagnostic.
- ///
- [JsonIgnore]
- public ICollection DebugMessages { get; init; } = new List();
-
- ///
- /// Gets a collection of informational messages, less critical than warnings, generally used for non-critical notifications.
- ///
- [JsonIgnore]
- public ICollection InformationMessages { get; init; } = new List();
-
- ///
- /// Gets a collection of messages indicating potential issues that are not necessarily errors, but which may require attention.
- ///
- [JsonIgnore]
- public ICollection WarningMessages { get; init; } = new List();
-
- ///
- /// Gets a collection of error messages indicating failures or problems within the service.
- ///
- [JsonIgnore]
- public ICollection ErrorMessages { get; init; } = new List();
-
- ///
- /// Gets a collection of messages indicating critical issues that require immediate attention.
- ///
- [JsonIgnore]
- public ICollection CriticalMessages { get; init; } = new List();
-
- ///
- /// Adds a new message to the collection of messages associated with the service operation.
- ///
- /// The message to add.
- /// The current instance of ServiceMessage, allowing for method chaining.
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- public IServiceMessage WithMessage(string message)
- {
- Messages.Add(message);
- return this;
- }
-
- ///
- /// Adds a message corresponding to the specified message key to the collection of messages associated with the service operation.
- /// This method uses the string representation of the enum value as the message.
- ///
- /// The enum value representing the message key.
- /// The current instance of ServiceMessage, allowing for method chaining.
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- public IServiceMessage WithMessageKey(Enum messageKey)
- {
- Messages.Add(messageKey.ToString());
- return this;
- }
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/ServiceMessageExtensions.cs b/DigitalData.Core.Application/ServiceMessageExtensions.cs
deleted file mode 100644
index 4fa7858..0000000
--- a/DigitalData.Core.Application/ServiceMessageExtensions.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-using DigitalData.Core.Contracts.Application;
-using Microsoft.Extensions.Localization;
-
-namespace DigitalData.Core.Application
-{
- ///
- /// Provides extension methods for IServiceMessage to enhance the usability of service messages
- /// by allowing easy addition of various types of messages including client, trace, debug, information,
- /// warning, error, and critical messages. These methods support both direct messages and enum-based keys
- /// for messages, facilitating localized or custom-formatted messages.
- ///
- public static class ServiceMessageExtensions
- {
- #region Flag
- ///
- /// Sets the specified flag on the service message or result, allowing for the categorization of the message based on specific conditions or statuses.
- ///
- /// The type of IServiceMessage.
- /// The service message instance to modify.
- /// The flag to set, indicating a specific condition or status.
- /// The service message instance with the updated flag, facilitating fluent chaining of methods.
- public static T WithFlag(this T serviceMessage, Enum flag) where T : IServiceMessage
- {
- serviceMessage.Flags.Add(flag);
- return serviceMessage;
- }
-
- ///
- /// Determines whether the service message has a flag indicating a security breach.
- ///
- /// The service message instance to check.
- /// True if the service message has the security breach flag; otherwise, false.
- public static bool HasSecurityBreachFlag(this IServiceMessage serviceMessage) => serviceMessage.HasFlag(Flag.SecurityBreach);
-
- ///
- /// Determines whether the service message has a flag indicating a data integrity issue.
- ///
- /// The service message instance to check.
- /// True if the service message has the data integrity issue flag; otherwise, false.
- public static bool HasDataIntegrityIssueFlag(this IServiceMessage serviceMessage) => serviceMessage.HasFlag(Flag.DataIntegrityIssue);
-
- ///
- /// Determines whether the service message has a flag indicating either a security breach or a data integrity issue, or both.
- /// This flag is used when it is not sure whether the problem is security or data integrity. In this case, data integrity should be checked first.
- ///
- /// The service message instance to check.
- /// True if the service message has the flag indicating either or both issues; otherwise, false.
- public static bool HasSecurityBreachOrDataIntegrityFlag(this IServiceMessage serviceMessage) => serviceMessage.HasFlag(Flag.SecurityBreachOrDataIntegrity);
- #endregion
-
- #region StringLocalizer
- ///
- /// Retrieves the localized string for the specified key.
- ///
- /// The key for the localized string.
- /// The localizer to use for retrieving the localized string.
- /// The localized string associated with the specified key.
- public static string LocalizedBy(this string key, IStringLocalizer localizer) => localizer[key];
-
- ///
- /// Retrieves the localized string for the specified enumeration key.
- ///
- /// The enumeration key for the localized string.
- /// The localizer to use for retrieving the localized string.
- /// The localized string associated with the specified enumeration key.
- public static string LocalizedBy(this Enum key, IStringLocalizer localizer) => localizer[key.ToString()];
- #endregion
-
- #region ClientMessage
- ///
- /// Adds a single client message to the service message.
- ///
- /// The service message to modify.
- /// The message to add.
- /// The modified service message instance.
- public static T WithClientMessage(this T serviceMessage, string message) where T : IServiceMessage
- {
- serviceMessage.ClientMessages.Add(message);
- return serviceMessage;
- }
- #endregion
-
- #region TraceMessages
- ///
- /// Adds a trace message to the service message.
- ///
- /// The service message to modify.
- /// The trace message to add.
- /// The modified service message instance.
- public static T WithTraceMessage(this T serviceMessage, string message) where T : IServiceMessage
- {
- serviceMessage.TraceMessages.Add(message);
- return serviceMessage;
- }
- #endregion
-
- #region DebugMessages
- ///
- /// Adds a debug message to the service message.
- ///
- /// The service message to modify.
- /// The debug message to add.
- /// The modified service message instance.
- public static T WithDebugMessage(this T serviceMessage, string message) where T : IServiceMessage
- {
- serviceMessage.DebugMessages.Add(message);
- return serviceMessage;
- }
- #endregion
-
- #region WarningMessages
- ///
- /// Adds a warning message to the service message.
- ///
- /// The service message to modify.
- /// The warning message to add.
- /// The modified service message instance.
- public static T WithWarningMessage(this T serviceMessage, string message) where T : IServiceMessage
- {
- serviceMessage.WarningMessages.Add(message);
- return serviceMessage;
- }
- #endregion
-
- #region ErrorMessages
- ///
- /// Adds an error message to the service message.
- ///
- /// The service message to modify.
- /// The error message to add.
- /// The modified service message instance.
- public static T WithErrorMessage(this T serviceMessage, string message) where T : IServiceMessage
- {
- serviceMessage.ErrorMessages.Add(message);
- return serviceMessage;
- }
- #endregion
-
- #region CriticalMessages
- ///
- /// Adds a critical message to the service message.
- ///
- /// The service message to modify.
- /// The critical message to add.
- /// The modified service message instance.
- public static T WithCriticalMessage(this T serviceMessage, string message) where T : IServiceMessage
- {
- serviceMessage.CriticalMessages.Add(message);
- return serviceMessage;
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/ServiceResult.cs b/DigitalData.Core.Application/ServiceResult.cs
deleted file mode 100644
index 1f3ad81..0000000
--- a/DigitalData.Core.Application/ServiceResult.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using DigitalData.Core.Contracts.Application;
-
-namespace DigitalData.Core.Application
-{
- ///
- /// Represents the outcome of a service operation, encapsulating the success or failure status,
- /// the data returned by the operation, and any associated messages.
- ///
- /// The type of data returned by the service operation, if any.
- public class ServiceResult : ServiceMessage, IServiceResult
- {
- ///
- /// Initializes a new instance of the ServiceResult class.
- public ServiceResult()
- {
- }
-
- ///
- /// Initializes a new instance of the ServiceResult class, specifying the success status is false and data.
- /// Optionally, a function for translating message keys can be provided.
- /// If a translation function is provided, it will be used for both string and enum message keys.
- ///
- /// The data associated with a successful operation.
- /// A function that translates a string key into its localized representation.
- /// If provided, it will also be adapted for translating enum keys by converting them to strings first.
- [Obsolete("Deprecated: initialize objects using object initializers instead.")]
- public ServiceResult(T? data)
- {
- Data = data;
- IsSuccess = false;
- }
-
- ///
- /// Initializes a new instance of the ServiceResult class with specified success status and data.
- ///
- /// The data associated with a successful operation.
- /// Indicates whether the service operation was successful.
- [Obsolete("Deprecated: initialize objects using object initializers instead.")]
- public ServiceResult(T? data, bool isSuccess) : base(isSuccess) => Data = data;
-
- ///
- /// Initializes a new instance of the ServiceResult class with specified success status, data, and messages.
- ///
- /// The data associated with a successful operation.
- /// Indicates whether the service operation was successful.
- /// An array of messages related to the operation's outcome.
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- public ServiceResult(T? data, bool isSuccess, params string[] messages) : base(isSuccess, messages) => Data = data;
-
- ///
- /// Gets or sets the data resulting from the service operation.
- ///
- public T? Data { get; set; } = default;
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Application/To.cs b/DigitalData.Core.Application/To.cs
deleted file mode 100644
index a10ea7a..0000000
--- a/DigitalData.Core.Application/To.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-namespace DigitalData.Core.Application
-{
- ///
- /// Specifies the destination of a message.
- ///
- public enum To
- {
- ///
- /// Indicates that the message is intended for the client.
- ///
- Client,
-
- ///
- /// Indicates that the message is intended for tracing purposes.
- ///
- Trace,
-
- ///
- /// Indicates that the message is intended for debugging purposes.
- ///
- Debug,
-
- ///
- /// Indicates that the message is informational.
- ///
- Information,
-
- ///
- /// Indicates that the message is a warning.
- ///
- Warning,
-
- ///
- /// Indicates that the message represents an error.
- ///
- Error,
-
- ///
- /// Indicates that the message represents a critical issue.
- ///
- Critical
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Contracts/Application/ICRUDService.cs b/DigitalData.Core.Contracts/Application/ICRUDService.cs
index 24c54e8..43fac72 100644
--- a/DigitalData.Core.Contracts/Application/ICRUDService.cs
+++ b/DigitalData.Core.Contracts/Application/ICRUDService.cs
@@ -1,58 +1,43 @@
using DigitalData.Core.Contracts.Infrastructure;
+using DigitalData.Core.DTO;
namespace DigitalData.Core.Contracts.Application
{
- ///
- /// Defines the contract for CRUD operations at the service level using Data Transfer Objects (DTOs) for entities of type TEntity,
- /// wrapped in an IServiceResult to encapsulate the outcome of the operation, including success, data, and error messages.
- ///
- /// The repository type that provides CRUD operations for entities of type TEntity.
- /// The type of the Data Transfer Object this service works with to create new entity.
- /// The type of the Data Transfer Object this service works with to read new entity.
- /// The type of the Data Transfer Object this service works with to update new entity.
- /// The type of the entity this service maps to.
- /// The type of the identifier for the entity.
- public interface ICRUDService : IServiceBase
+ public interface ICRUDService
where TCRUDRepository : ICRUDRepository where TCreateDto : class where TReadDto : class where TUpdateDto : class where TEntity : class
{
- ///
- /// Creates a new entity based on the provided DTO and returns the result wrapped in an IServiceResult,
- /// including the created entity on success or an error message on failure.
- ///
- /// The createDto to create a new entity from.
- /// An IServiceResult containing the id of created entity or an error message.
- Task> CreateAsync(TCreateDto createDto);
+ Task> CreateAsync(TCreateDto createDto);
///
/// Retrieves an entity by its identifier and returns its readDTO representation wrapped in an IServiceResult,
/// including the readDTO on success or null and an error message on failure.
///
/// The identifier of the entity to retrieve.
- /// An IServiceResult containing the readDTO representing the found entity or null, with an appropriate message.
- Task> ReadByIdAsync(TId id);
+ /// An DataResult containing the readDTO representing the found entity or null, with an appropriate message.
+ Task> ReadByIdAsync(TId id);
///
/// Retrieves all entities and returns their readDTO representations wrapped in an IServiceResult,
/// including a collection of readDTOs on success or an error message on failure.
///
- /// An IServiceResult containing a collection of readDTOs representing all entities or an error message.
- Task>> ReadAllAsync();
+ /// An DataResult containing a collection of readDTOs representing all entities or an error message.
+ Task>> ReadAllAsync();
///
/// Updates an existing entity based on the provided updateDTO and returns the result wrapped in an IServiceMessage,
/// indicating the success or failure of the operation, including the error messages on failure.
///
/// The updateDTO with updated values for the entity.
- /// An IServiceMessage indicating the outcome of the update operation, with an appropriate message.
- Task UpdateAsync(TUpdateDto updateDto);
+ /// An Result indicating the outcome of the update operation, with an appropriate message.
+ Task UpdateAsync(TUpdateDto updateDto);
///
/// Deletes an entity by its identifier and returns the result wrapped in an IServiceMessage,
/// indicating the success or failure of the operation, including the error messages on failure.
///
/// The identifier of the entity to delete.
- /// An IServiceMessage indicating the outcome of the delete operation, with an appropriate message.
- Task DeleteAsyncById(TId id);
+ /// An Result indicating the outcome of the delete operation, with an appropriate message.
+ Task DeleteAsyncById(TId id);
///
/// Asynchronously checks if an entity with the specified identifier exists within the data store.
diff --git a/DigitalData.Core.Contracts/Application/IDirectorySearchService.cs b/DigitalData.Core.Contracts/Application/IDirectorySearchService.cs
index 226827f..12f0c91 100644
--- a/DigitalData.Core.Contracts/Application/IDirectorySearchService.cs
+++ b/DigitalData.Core.Contracts/Application/IDirectorySearchService.cs
@@ -1,8 +1,9 @@
-using System.DirectoryServices;
+using DigitalData.Core.DTO;
+using System.DirectoryServices;
namespace DigitalData.Core.Contracts.Application
{
- public interface IDirectorySearchService : IServiceBase
+ public interface IDirectorySearchService
{
public string ServerName { get; }
@@ -14,9 +15,9 @@ namespace DigitalData.Core.Contracts.Application
bool ValidateCredentials(string dirEntryUsername, string dirEntryPassword);
- IServiceResult> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties);
+ DataResult> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties);
- IServiceResult> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties);
+ DataResult> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties);
void SetSearchRootCache(string username, string password);
diff --git a/DigitalData.Core.Contracts/Application/IResponseService.cs b/DigitalData.Core.Contracts/Application/IResponseService.cs
deleted file mode 100644
index d55f994..0000000
--- a/DigitalData.Core.Contracts/Application/IResponseService.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-namespace DigitalData.Core.Contracts.Application
-{
- ///
- /// Defines the base functionality for a service, including creating service messages and results.
- ///
- public interface IResponseService
- {
- #region WITHOUT_MESSAGE
-
- ///
- /// Creates a simple service message indicating success or failure without any additional messages.
- ///
- /// Indicates if the operation was successful.
- /// A service message indicating the outcome of the operation without any messages.
- IServiceMessage CreateMessage(bool isSuccess);
-
- ///
- /// Creates a service result with the specified data and a success flag, without any additional messages.
- ///
- /// The type of data the service result will contain.
- /// The data for the service result.
- /// Indicates if the operation was successful.
- /// A service result containing the data and indicating the outcome of the operation without any messages.
- IServiceResult CreateResult(T? data, bool isSuccess);
-
- ///
- /// Creates a service message indicating a successful operation without any messages.
- ///
- /// A service message indicating a successful operation.
- IServiceMessage Successful();
-
- ///
- /// Creates a service message indicating a failed operation without any messages.
- ///
- /// A service message indicating a failed operation.
- IServiceMessage Failed();
-
- ///
- /// Creates a successful service result with the specified data, without any messages.
- ///
- /// The type of data the service result will contain.
- /// The data to include in the service result.
- /// A successful service result containing the data, indicating a successful operation without any messages.
- IServiceResult Successful(T data);
-
- ///
- /// Creates a failed service result, optionally including data, without any messages.
- ///
- /// The type of data the service result can contain.
- /// Optional data to include in the failed service result.
- /// A failed service result, which may or may not contain data, indicating a failed operation without any messages.
- IServiceResult Failed(T? data = default);
-
- #endregion
- #region WITH_STRING_MESSAGE
-
- ///
- /// Creates a service message.
- ///
- /// Indicates if the operation was successful.
- /// The messages associated with the operation.
- /// A service message indicating the outcome of the operation and any associated messages.
- IServiceMessage CreateMessage(bool isSuccess, params string[] messages);
-
- ///
- /// Creates a service result with the specified data.
- ///
- /// The type of data the service result will contain.
- /// The data for the service result.
- /// Indicates if the operation was successful.
- /// The messages associated with the operation.
- /// A service result containing the data and indicating the outcome of the operation.
- IServiceResult CreateResult(T? data, bool isSuccess, params string[] messages);
-
- ///
- /// Creates a successful service message.
- ///
- /// The success messages.
- /// A successful service message.
- IServiceMessage Successful(params string[] messages);
-
- ///
- /// Creates a failed service message.
- ///
- /// The failure messages.
- /// A failed service message.
- IServiceMessage Failed(params string[] messages);
-
- ///
- /// Creates a successful service result with the specified data.
- ///
- /// The type of data the service result will contain.
- /// The data to include in the service result.
- /// The success messages.
- /// A successful service result containing the data.
- IServiceResult Successful(T data, params string[] messages);
-
- ///
- /// Creates a failed service result, optionally including data.
- ///
- /// The type of data the service result can contain.
- /// Optional data to include in the failed service result.
- /// The failure messages.
- /// A failed service result, which may or may not contain data.
- IServiceResult Failed(T? data = default, params string[] messages);
-
- ///
- /// Creates a failed service result without explicitly including data, using only failure messages.
- ///
- ///
- /// This overload is useful when you want to indicate a failure without the need to return any specific data,
- /// but still want to provide details about the failure through messages.
- ///
- /// The type of data the service result can contain. The result will contain the default value for this type.
- /// An array of failure messages associated with the operation. These provide detail about why the operation failed.
- /// A failed service result. The data part of the result will be set to the default value for the specified type.
- IServiceResult Failed(params string[] messages);
-
- #endregion
- #region WITH_ENUM_MESSAGE
-
- ///
- /// Creates a service message using enumeration values.
- ///
- /// Indicates if the operation was successful.
- /// The enumeration values associated with the operation.
- /// A service message indicating the outcome of the operation and any associated enumeration values.
- IServiceMessage CreateMessage(bool isSuccess, params Enum[] messages);
-
- ///
- /// Creates a service result with the specified data and enumeration values for messages.
- ///
- /// The type of data the service result will contain.
- /// The data for the service result.
- /// Indicates if the operation was successful.
- /// The enumeration values associated with the operation.
- /// A service result containing the data and indicating the outcome of the operation with enumeration values.
- IServiceResult CreateResult(T? data, bool isSuccess, params Enum[] messages);
-
- ///
- /// Creates a successful service message using enumeration values.
- ///
- /// The success enumeration values.
- /// A successful service message.
- IServiceMessage Successful(params Enum[] messages);
-
- ///
- /// Creates a failed service message using enumeration values.
- ///
- /// The failure enumeration values.
- /// A failed service message.
- IServiceMessage Failed(params Enum[] messages);
-
- ///
- /// Creates a successful service result with the specified data, using enumeration values for messages.
- ///
- /// The type of data the service result will contain.
- /// The data to include in the service result.
- /// The success enumeration values.
- /// A successful service result containing the data.
- IServiceResult Successful(T data, params Enum[] messages);
-
- ///
- /// Creates a failed service result, optionally including data, using enumeration values for messages.
- ///
- /// The type of data the service result can contain.
- /// Optional data to include in the failed service result.
- /// The failure enumeration values.
- /// A failed service result, which may or may not contain data.
- IServiceResult Failed(T? data = default, params Enum[] messages);
-
- ///
- /// Creates a failed service result without explicitly including data, using only enumeration values for failure messages.
- ///
- ///
- /// This overload is useful when you want to indicate a failure without the need to return any specific data,
- /// but still want to provide details about the failure through enumeration values.
- ///
- /// The type of data the service result can contain. The result will contain the default value for this type.
- /// An array of enumeration values associated with the operation. These provide detail about why the operation failed.
- /// A failed service result. The data part of the result will be set to the default value for the specified type.
- IServiceResult Failed(params Enum[] messages);
- #endregion
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Contracts/Application/IServiceBase.cs b/DigitalData.Core.Contracts/Application/IServiceBase.cs
deleted file mode 100644
index f0eb10f..0000000
--- a/DigitalData.Core.Contracts/Application/IServiceBase.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace DigitalData.Core.Contracts.Application
-{
- public interface IServiceBase : IResponseService
- {
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Contracts/Application/IServiceMessage.cs b/DigitalData.Core.Contracts/Application/IServiceMessage.cs
deleted file mode 100644
index 6641366..0000000
--- a/DigitalData.Core.Contracts/Application/IServiceMessage.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace DigitalData.Core.Contracts.Application
-{
- ///
- /// Defines a structured format for service messages, categorizing them into success indicators and various types of messages.
- /// This interface segregates messages into client-facing messages and different levels of logging messages, facilitating targeted communications and diagnostics.
- /// Properties are initialized once per instance and cannot be modified afterwards, promoting immutability.
- ///
- public interface IServiceMessage
- {
- ///
- /// Gets or sets a value indicating whether the service operation was successful.
- ///
- bool IsSuccess { get; set; }
-
- ///
- /// Represents the list of flags that indicate specific types of statuses or conditions in a service operation.
- /// These flags help in categorizing the state of the operation more granularly, allowing for multiple conditions to be represented simultaneously.
- ///
- [JsonIgnore]
- public ICollection Flags { get; }
-
- ///
- /// Checks if any of the current service message's flags matches the specified flag based on their string representations.
- /// This method is useful for conditional logic where the exact string representation of the flag values is crucial.
- ///
- /// The flag to check against the current service message's flags.
- /// true if a flag with a matching string representation exists; otherwise, false.
- public bool HasFlag(Enum flag) => Flags.Any(f => f.ToString() == flag.ToString());
-
- ///
- /// [Obsolete("Deprecated: Use ClientMessages instead.")]
- /// Gets a collection of messages associated with the service operation. These messages can be error descriptions,
- /// success notifications, or other relevant information related to the operation's outcome.
- ///
- [Obsolete("Deprecated: Use ClientMessages instead.")]
- ICollection Messages { get; init; }
-
- ///
- /// Gets a collection of messages intended for client display. This replaces the deprecated 'Messages' property.
- ///
- ICollection ClientMessages { get; init; }
-
- ///
- /// Gets a collection of messages used for tracing program execution at a fine-grained level. These are typically voluminous and detailed.
- ///
- [JsonIgnore]
- ICollection TraceMessages { get; init; }
-
- ///
- /// Gets a collection of messages helpful for debugging during development. These messages are often diagnostic.
- ///
- [JsonIgnore]
- ICollection DebugMessages { get; init; }
-
- ///
- /// Gets a collection of informational messages, less critical than warnings, generally used for non-critical notifications.
- ///
- [JsonIgnore]
- ICollection InformationMessages { get; init; }
-
- ///
- /// Gets a collection of messages indicating potential issues that are not necessarily errors, but which may require attention.
- ///
- [JsonIgnore]
- ICollection WarningMessages { get; init; }
-
- ///
- /// Gets a collection of error messages indicating failures or problems within the service.
- ///
- [JsonIgnore]
- ICollection ErrorMessages { get; init; }
-
- ///
- /// Gets a collection of messages indicating critical issues that require immediate attention.
- ///
- [JsonIgnore]
- ICollection CriticalMessages { get; init; }
-
- ///
- /// Adds a new message to the appropriate collection based on the message type.
- ///
- /// The message to add.
- /// The current instance of IServiceMessage, allowing for method chaining.
- IServiceMessage WithMessage(string message);
-
- ///
- /// Adds a message corresponding to a specified message key to the appropriate collection, facilitating localization and standardization.
- ///
- /// The enum value representing the message key.
- /// The current instance of IServiceMessage, allowing for method chaining.
- IServiceMessage WithMessageKey(Enum messageKey);
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Contracts/Application/IServiceResult.cs b/DigitalData.Core.Contracts/Application/IServiceResult.cs
deleted file mode 100644
index 43f2e1e..0000000
--- a/DigitalData.Core.Contracts/Application/IServiceResult.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace DigitalData.Core.Contracts.Application
-{
- ///
- /// Represents the outcome of a service operation, extending IServiceMessage with the addition of a data payload.
- /// This interface is generic, allowing for the specification of the type of data returned by the service operation.
- /// It is used to communicate not just the success or failure of an operation, but also to return any relevant data
- /// along with the operation's outcome.
- ///
- /// The type of the data associated with the service operation's outcome. This could be a model,
- /// a collection of models, or any other type relevant to the operation.
- public interface IServiceResult : IServiceMessage
- {
- ///
- /// Gets or sets the data resulting from the service operation. This property is nullable to accommodate operations
- /// that might not return data upon failure.
- ///
- T? Data { get; set; }
- }
-}
\ No newline at end of file
diff --git a/DigitalData.Core.Contracts/DigitalData.Core.Contracts.csproj b/DigitalData.Core.Contracts/DigitalData.Core.Contracts.csproj
index 864bace..e38fcb3 100644
--- a/DigitalData.Core.Contracts/DigitalData.Core.Contracts.csproj
+++ b/DigitalData.Core.Contracts/DigitalData.Core.Contracts.csproj
@@ -24,6 +24,10 @@
+
+
+
+
Never
diff --git a/DigitalData.Core.Contracts/IFlag.cs b/DigitalData.Core.Contracts/IFlag.cs
new file mode 100644
index 0000000..4e1aa0f
--- /dev/null
+++ b/DigitalData.Core.Contracts/IFlag.cs
@@ -0,0 +1,7 @@
+namespace DigitalData.Core.Contracts
+{
+ internal interface IError
+ {
+
+ }
+}
diff --git a/DigitalData.Core.Application/AutoMapperExtension.cs b/DigitalData.Core.DTO/AutoMapperExtension.cs
similarity index 96%
rename from DigitalData.Core.Application/AutoMapperExtension.cs
rename to DigitalData.Core.DTO/AutoMapperExtension.cs
index bb61521..44401ec 100644
--- a/DigitalData.Core.Application/AutoMapperExtension.cs
+++ b/DigitalData.Core.DTO/AutoMapperExtension.cs
@@ -1,6 +1,6 @@
using AutoMapper;
-namespace DigitalData.Core.Application
+namespace DigitalData.Core.DTO
{
public static class AutoMapperExtension
{
diff --git a/DigitalData.Core.Application/DTO/CookieConsentSettings.cs b/DigitalData.Core.DTO/CookieConsentSettings.cs
similarity index 98%
rename from DigitalData.Core.Application/DTO/CookieConsentSettings.cs
rename to DigitalData.Core.DTO/CookieConsentSettings.cs
index 9243cd1..004aad7 100644
--- a/DigitalData.Core.Application/DTO/CookieConsentSettings.cs
+++ b/DigitalData.Core.DTO/CookieConsentSettings.cs
@@ -1,4 +1,4 @@
-namespace DigitalData.Core.Application.DTO
+namespace DigitalData.Core.DTO
{
///
/// Represents settings related to user cookie consent dialogs. Designed to be serialized into JSON format for use with JavaScript frontend libraries,
diff --git a/DigitalData.Core.DTO/DIExtensions.cs b/DigitalData.Core.DTO/DIExtensions.cs
new file mode 100644
index 0000000..7d51b46
--- /dev/null
+++ b/DigitalData.Core.DTO/DIExtensions.cs
@@ -0,0 +1,22 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using System.Configuration;
+
+namespace DigitalData.Core.DTO
+{
+ public static class DIExtensions
+ {
+ public static IServiceCollection AddCookieConsentSettings(this IServiceCollection services)
+ {
+ services.AddSingleton(sp =>
+ {
+ var configuration = sp.GetRequiredService();
+ var settings = configuration.GetSection("CookieConsentSettings").Get();
+ return settings is null
+ ? throw new ConfigurationErrorsException("The 'CookieConsentSettings' section is missing or improperly configured in appsettings.json.")
+ : settings;
+ });
+ return services;
+ }
+ }
+}
diff --git a/DigitalData.Core.DTO/DTOExtensions.cs b/DigitalData.Core.DTO/DTOExtensions.cs
new file mode 100644
index 0000000..054aeac
--- /dev/null
+++ b/DigitalData.Core.DTO/DTOExtensions.cs
@@ -0,0 +1,110 @@
+using Microsoft.Extensions.Logging;
+using System.Text;
+
+namespace DigitalData.Core.DTO
+{
+ public static class DTOExtensions
+ {
+ public static T Message(this T result, string message) where T : Result
+ {
+ result.Messages.Add(message);
+ return result;
+ }
+
+ public static T Message(this T result, params string[] messages) where T : Result
+ {
+ result.Messages.AddRange(messages);
+ return result;
+ }
+
+ public static T Notice(this T result, Notice notice) where T : Result
+ {
+ result.Notices.Add(notice);
+ return result;
+ }
+
+ public static T Notice(this T result, params Notice[] notices) where T : Result
+ {
+ result.Notices.AddRange(notices);
+ return result;
+ }
+
+ public static T Notice(this T result, LogLevel level, params Enum[] flags) where T : Result
+ {
+ var notices = flags.Select(flag => new Notice()
+ {
+ Flag = flag,
+ Level = level
+ });
+ result.Notices.AddRange(notices);
+ return result;
+ }
+
+ public static T Notice(this T result, LogLevel level, Enum flag, params string[] messages) where T : Result
+ {
+ result.Notices.Add(new Notice()
+ {
+ Flag = flag,
+ Level = level,
+ Messages = messages.ToList()
+ });
+ return result;
+ }
+
+ public static T Notice(this T result, LogLevel level, params string[] messages) where T : Result
+ {
+ result.Notices.Add(new Notice()
+ {
+ Flag = null,
+ Level = level,
+ Messages = messages.ToList()
+ });
+ return result;
+ }
+
+ public static I Then(this Result result, Func Try, Func, List, I> Catch)
+ {
+ return result.IsSuccess ? Try() : Catch(result.Messages, result.Notices);
+ }
+
+ public static I Then(this DataResult result, Func Try, Func, List, I> Catch)
+ {
+ return result.IsSuccess ? Try(result.Data) : Catch(result.Messages, result.Notices);
+ }
+
+ public static async Task Then(this Task tResult, Func Try, Func, List, I> Catch)
+ {
+ Result result = await tResult;
+ return result.IsSuccess ? Try() : Catch(result.Messages, result.Notices);
+ }
+
+ public static async Task Then(this Task> tResult, Func Try, Func, List, I> Catch)
+ {
+ DataResult result = await tResult;
+ return result.IsSuccess ? Try(result.Data) : Catch(result.Messages, result.Notices);
+ }
+
+ public static void LogNotice(this ILogger logger, IEnumerable notices, string start = ": ", string seperator = ". ", string end = ".\n")
+ {
+ foreach(LogLevel level in Enum.GetValues(typeof(LogLevel)))
+ {
+ var logNotices = notices.Where(n => n.Level == level);
+
+ if (!logNotices.Any())
+ continue;
+
+ var sb = new StringBuilder();
+ foreach(Notice notice in logNotices)
+ {
+ if (notice.Flag is not null)
+ sb.Append(notice.Flag);
+
+ if (notice.Messages.Any())
+ sb.Append(start).Append(string.Join(seperator, notice.Messages)).AppendLine(end);
+ else sb.Append(end);
+ }
+ logger.Log(level, sb.ToString());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DigitalData.Core.DTO/DataResult.cs b/DigitalData.Core.DTO/DataResult.cs
new file mode 100644
index 0000000..a5ed5fb
--- /dev/null
+++ b/DigitalData.Core.DTO/DataResult.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace DigitalData.Core.DTO
+{
+ public class DataResult : Result
+ {
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public required T Data { get; init; }
+ }
+}
\ No newline at end of file
diff --git a/DigitalData.Core.DTO/DigitalData.Core.DTO.csproj b/DigitalData.Core.DTO/DigitalData.Core.DTO.csproj
new file mode 100644
index 0000000..8a17f62
--- /dev/null
+++ b/DigitalData.Core.DTO/DigitalData.Core.DTO.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DigitalData.Core.Application/Flag.cs b/DigitalData.Core.DTO/Flag.cs
similarity index 97%
rename from DigitalData.Core.Application/Flag.cs
rename to DigitalData.Core.DTO/Flag.cs
index 9649926..bc2508b 100644
--- a/DigitalData.Core.Application/Flag.cs
+++ b/DigitalData.Core.DTO/Flag.cs
@@ -1,4 +1,4 @@
-namespace DigitalData.Core.Application
+namespace DigitalData.Core.DTO
{
///
/// Defines flags that indicate specific types of status or conditions in a service operation.
diff --git a/DigitalData.Core.DTO/Notice.cs b/DigitalData.Core.DTO/Notice.cs
new file mode 100644
index 0000000..5094f9b
--- /dev/null
+++ b/DigitalData.Core.DTO/Notice.cs
@@ -0,0 +1,11 @@
+using Microsoft.Extensions.Logging;
+
+namespace DigitalData.Core.DTO
+{
+ public class Notice
+ {
+ public Enum? Flag { get; init; } = null;
+ public LogLevel Level { get; init; } = LogLevel.None;
+ public List Messages { get; init; } = new();
+ }
+}
\ No newline at end of file
diff --git a/DigitalData.Core.DTO/Result.cs b/DigitalData.Core.DTO/Result.cs
new file mode 100644
index 0000000..c1892f9
--- /dev/null
+++ b/DigitalData.Core.DTO/Result.cs
@@ -0,0 +1,40 @@
+using System.Text.Json.Serialization;
+
+namespace DigitalData.Core.DTO
+{
+ public class Result
+ {
+ public bool IsSuccess { get; set; } = false;
+
+ public List Messages { get; init; } = new();
+
+ [JsonIgnore]
+ public List Notices = new();
+
+ public DataResult Data(T data) => new()
+ {
+ IsSuccess = IsSuccess,
+ Messages = Messages,
+ Notices = Notices,
+ Data = data
+ };
+
+ public static Result Success() => new() { IsSuccess = true };
+
+ public static Result Fail() => new() { IsSuccess = false };
+
+ public static DataResult Success(T data) => new()
+ {
+ IsSuccess = true,
+ Data = data
+ };
+
+#pragma warning disable CS8601 // Possible null reference assignment.
+ public static DataResult Fail() => new()
+ {
+ IsSuccess = false,
+ Data = default
+ };
+#pragma warning restore CS8601 // Possible null reference assignment.
+ }
+}
\ No newline at end of file
diff --git a/DigitalData.Core.Infrastructure/CRUDRepository.cs b/DigitalData.Core.Infrastructure/CRUDRepository.cs
index 96a448b..80bbf83 100644
--- a/DigitalData.Core.Infrastructure/CRUDRepository.cs
+++ b/DigitalData.Core.Infrastructure/CRUDRepository.cs
@@ -78,5 +78,11 @@ namespace DigitalData.Core.Infrastructure
var result = await _dbContext.SaveChangesAsync();
return result > 0;
}
+
+ ///
+ /// Asynchronously counts all entities in the repository.
+ ///
+ /// The total number of entities in the repository.
+ public virtual async Task CountAsync() => await _dbSet.CountAsync();
}
}
\ No newline at end of file
diff --git a/DigitalData.Core.sln b/DigitalData.Core.sln
index 71c0cce..8cd090c 100644
--- a/DigitalData.Core.sln
+++ b/DigitalData.Core.sln
@@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.API", "Dig
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Tests", "DigitalData.Core.Tests\DigitalData.Core.Tests.csproj", "{B54DEF90-C30C-44EA-9875-76F1B330CBB7}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.DTO", "DigitalData.Core.DTO\DigitalData.Core.DTO.csproj", "{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -39,6 +41,10 @@ Global
{B54DEF90-C30C-44EA-9875-76F1B330CBB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B54DEF90-C30C-44EA-9875-76F1B330CBB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B54DEF90-C30C-44EA-9875-76F1B330CBB7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE