diff --git a/DI/XDIHelperExtension.cs b/DI/XDIHelperExtension.cs
new file mode 100644
index 0000000..d7a041f
--- /dev/null
+++ b/DI/XDIHelperExtension.cs
@@ -0,0 +1,103 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using xCommons.Extensions;
+using xExceptions.Constants;
+using xFileService.Interfaces;
+using xFileService.Providers;
+
+namespace xFileService.DI
+{
+ public static class XDIHelperExtension
+ {
+ ///
+ /// Register Module Provided Service on DI
+ ///
+ ///
+ ///
+ public static void AddXFileService(
+ this IServiceCollection services,
+ ServiceLifetime lifeTime
+ )
+ {
+ //
+ AddFileService(
+ services,
+ lifeTime
+ );
+ }
+
+ //
+ #region Private ...
+ ///
+ /// a LogTag for Service ...
+ ///
+ private static string XLogTag = "XFileService";
+
+ ///
+ /// print a log in Console ...
+ ///
+ ///
+ private static void Log(string message)
+ {
+ Console.WriteLine($"{XLogTag} => {message}");
+ }
+
+ ///
+ /// Register Push Service ...
+ ///
+ ///
+ ///
+ private static void AddFileService(
+ IServiceCollection services,
+ ServiceLifetime lifeTime
+ )
+ {
+ //
+ var exception = XException.InvalidArgs.ToException(); ;
+
+ //
+ // Services ...
+ var isServicesExists = !services.IsNull();
+ if (!isServicesExists)
+ {
+ //
+ Log("AddFileService failed, services not provided ...");
+ throw exception;
+ }
+
+ //
+ // Lifetime ...
+ var isLifetimeExists = !lifeTime.IsNull();
+ if (!isLifetimeExists)
+ {
+ //
+ Log("AddFileService failed, lifetime not provided ...");
+ throw exception;
+ }
+
+ //
+ // Check String Repository Exists ...
+ var isRepositoryExists = !services
+ .GetRegisteredService()
+ .IsNull();
+ if (!isRepositoryExists)
+ {
+ //
+ Log("AddFileService failed, IXTagRepository not provided ...");
+ throw exception;
+ }
+
+ //
+ // Register Main Provider ...
+ services.Add(new ServiceDescriptor(typeof(IXFileProvider), typeof(XFileProvider), lifeTime));
+
+ //
+ Log("AddFileService Succeed ...");
+ }
+ #endregion
+ }
+
+ internal class IXTagRepository
+ {
+ }
+}
\ No newline at end of file
diff --git a/Extensions/xFileServiceExtensions.cs b/Extensions/xFileServiceExtensions.cs
new file mode 100644
index 0000000..6ea5897
--- /dev/null
+++ b/Extensions/xFileServiceExtensions.cs
@@ -0,0 +1,45 @@
+using xCommons.Extensions;
+using xFileService.Models.Dtos;
+using xFileService.Models.Entities;
+
+namespace xFileService.Extensions
+{
+ public static class xFileServiceExtensions
+ {
+ ///
+ /// Map Global Properties From XFile to XFile Dto ...
+ ///
+ ///
+ ///
+ public static XFileDto ToXFileDto(this XFile source)
+ {
+ //
+ XFileDto result = null;
+
+ //
+ if (!source.IsNullOrDefault())
+ {
+ //
+ result = new XFileDto();
+ result = result.UpdateData(source);
+
+ //
+ // result = new XFileDto
+ // {
+ // Id = source.Id,
+ // Type = source.Type,
+ // OwnerId = source.OwnerId,
+ // Name = source.Name,
+ // Path = source.Path,
+ // Thumb = source.Thumb,
+ // ThumbPath = source.ThumbPath,
+ // UploadedOn = source.UploadedOn,
+ // FileName = source.FileName
+ // };
+ }
+
+ //
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Hubs/XFileEntityHub.cs b/Hubs/XFileEntityHub.cs
new file mode 100644
index 0000000..2b0e4ed
--- /dev/null
+++ b/Hubs/XFileEntityHub.cs
@@ -0,0 +1,16 @@
+using System;
+using Microsoft.Extensions.Logging;
+using xFileService.Models.Entities;
+using xPushService.Base;
+
+namespace xFileService.Hubs
+{
+ public class XFileEntityHub : XBaseEntityHub
+ {
+ //
+ #region Constructor ...
+ public XFileEntityHub(ILogger logger) : base(logger)
+ { }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Interfaces/IXFileProvider.cs b/Interfaces/IXFileProvider.cs
new file mode 100644
index 0000000..d6fe1b5
--- /dev/null
+++ b/Interfaces/IXFileProvider.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.SignalR;
+using xDataService.Configuration;
+using xFileService.Hubs;
+using xFileService.Interfaces.Entities;
+using xFileService.Models.Dtos;
+using xFileService.Models.Entities;
+using xIdentityModels.Models;
+using xIdentityService.Interfaces;
+using xModels.Dtos;
+using xStorageService.Interfaces;
+using XFileDto = xFileService.Models.Dtos.XFileDto;
+
+namespace xFileService.Interfaces
+{
+ public interface IXFileProvider
+ {
+ //
+ #region Props ...
+ IHubContext Hub { get; }
+ IXFileRepository FileRepository { get; }
+ IXStorageProvider StorageProvider { get; }
+ IXIdentityProvider IdentityProvider { get; }
+ XDataServiceConfiguration DataSercviceConfiguration { get; }
+ #endregion
+
+ //
+ #region Tools ...
+ ///
+ /// Stream Specified File ...
+ ///
+ ///
+ ///
+ Task Stream(Guid id);
+
+ ///
+ /// Stream Specified File ...
+ ///
+ ///
+ ///
+ Task Stream(string fileName);
+
+ ///
+ /// Download Specified File ...
+ ///
+ ///
+ ///
+ Task Download(Guid id);
+
+ ///
+ /// Download Specified File ...
+ ///
+ ///
+ ///
+ Task Download(string fileName);
+
+ ///
+ /// Upload Files ...
+ ///
+ ///
+ ///
+ ///
+ Task> Upload(
+ IFormFileCollection files,
+ XUserClaimsInfoDto userInfo = null
+ );
+
+ ///
+ /// Remove Specified Files ...
+ ///
+ ///
+ ///
+ ///
+ Task> Remove(
+ string ids,
+ XUserClaimsInfoDto userInfo = null
+ );
+
+ ///
+ /// Retrieve Specified File Streaming Info ...
+ ///
+ ///
+ ///
+ Task GetFileDescriptor(Guid id);
+
+ ///
+ /// Retrieve Specified File Streaming Info ...
+ ///
+ ///
+ ///
+ Task GetFileDescriptor(string fileName);
+ #endregion
+
+ //
+ #region Data Model ...
+ ///
+ /// Get Specified File Model ...
+ ///
+ ///
+ ///
+ ///
+ Task Get(
+ Guid id
+ );
+
+ ///
+ /// Get All Exists File Models ...
+ ///
+ ///
+ ///
+ Task> GetAll();
+
+ ///
+ /// find an Entity by providing a Conditional Expression ...
+ ///
+ ///
+ Task FindOne(Expression> whereClause);
+
+ ///
+ /// find a collection of Entities by proving a Conditional Expression ...
+ ///
+ ///
+ ///
+ Task> FindMany(
+ Expression> whereClause
+ );
+
+ ///
+ /// retrieve Entities based on XQuery Pagination structure ...
+ ///
+ ///
+ ///
+ Task> Query(
+ XQuery query
+ );
+
+ ///
+ /// retrieve Entities based on XQuery Pagination structure by providing a Conditional Expression ...
+ ///
+ ///
+ ///
+ ///
+ Task> ConditionalQuery(
+ Expression> whereClause,
+ XQuery query
+ );
+
+ ///
+ /// Update an Entity values ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task Update(
+ Guid id,
+ XFileDto item,
+ XUserClaimsInfoDto userInfo = null
+ );
+
+ ///
+ /// remove an Entity ...
+ ///
+ ///
+ ///
+ ///
+ Task Remove(
+ Guid id,
+ XUserClaimsInfoDto userInfo = null
+ );
+
+ ///
+ /// count all exists Entities ...
+ ///
+ ///
+ Task Count();
+
+ ///
+ /// Check an Entity exists or not ...
+ ///
+ ///
+ ///
+ Task IsExists(
+ Guid id
+ );
+ #endregion
+
+ //
+ #region Helpers ...
+ ///
+ /// Converts an Entity to Dto ...
+ ///
+ ///
+ ///
+ Task ToXFileDto(XFile model);
+
+ ///
+ /// Convert a List of Entities to Dto ...
+ ///
+ ///
+ ///
+ Task> ToXDtoList(IEnumerable list);
+
+ ///
+ /// Converts an Entity Query Result to Dto ...
+ ///
+ ///
+ ///
+ Task> ToXDtoQueryResult(XQueryResult queryResult);
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Providers/XFileProvider.cs b/Providers/XFileProvider.cs
new file mode 100644
index 0000000..97ba421
--- /dev/null
+++ b/Providers/XFileProvider.cs
@@ -0,0 +1,967 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.SignalR;
+using xCommons.Extensions;
+using xDataService.Configuration;
+using xExceptions.Constants;
+using xFileService.Extensions;
+using xFileService.Hubs;
+using xFileService.Interfaces;
+using xFileService.Interfaces.Entities;
+using xFileService.Models.Dtos;
+using xFileService.Models.Entities;
+using xIdentityModels.Models;
+using xIdentityService.Interfaces;
+using xModels.Dtos;
+using xIdentityService.Extensions;
+using XFileDto = xFileService.Models.Dtos.XFileDto;
+using xStorageService.Interfaces;
+using System.IO;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.AspNetCore.StaticFiles;
+using System.Linq;
+
+namespace xFileService.Providers
+{
+ public class XFileProvider : IXFileProvider
+ {
+ //
+ #region Props ...
+ public IHubContext Hub { get; }
+ public IXFileRepository FileRepository { get; }
+ public IXStorageProvider StorageProvider { get; }
+ public IXIdentityProvider IdentityProvider { get; }
+ public XDataServiceConfiguration DataSercviceConfiguration { get; }
+ #endregion
+
+ //
+ #region Constructor ...
+ public XFileProvider(
+ IXFileRepository fileRepository,
+ IXStorageProvider storageProvider,
+ IXIdentityProvider identityProvider,
+ XDataServiceConfiguration dataSercviceConfiguration,
+ IHubContext hub = null
+ )
+ {
+ //
+ Hub = hub;
+ FileRepository = fileRepository;
+ StorageProvider = storageProvider;
+ IdentityProvider = identityProvider;
+ DataSercviceConfiguration = dataSercviceConfiguration;
+ }
+ #endregion
+
+ //
+ #region Tools ...
+ ///
+ /// Stream Specified File ...
+ ///
+ ///
+ ///
+ public async Task Stream(Guid id)
+ {
+ //
+ // Validate Args ...
+ var isValid = !id.IsNull() &&
+ !id.IsDefaultGuid();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Generate Stream Info and Validate it ...
+ var stream = await GetFileDescriptor(id);
+ if (stream.IsNull())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Result Model ...
+ var result = new FileStreamResult(
+ stream.Stream,
+ stream.MIMEType
+ )
+ {
+ FileDownloadName = stream.Name
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Stream Specified File ...
+ ///
+ ///
+ ///
+ public async Task Stream(string fileName)
+ {
+ //
+ // Validate Args ...
+ var isValid = !fileName.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Generate Stream Info and Validate it ...
+ var stream = await GetFileDescriptor(fileName);
+ if (stream.IsNull())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Result Model ...
+ var result = new FileStreamResult(
+ stream.Stream,
+ stream.MIMEType
+ )
+ {
+ FileDownloadName = stream.Name
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Download Specified File ...
+ ///
+ ///
+ ///
+ public async Task Download(Guid id)
+ {
+ //
+ // Validate Args ...
+ var isValid = !id.IsNull() &&
+ !id.IsDefaultGuid();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Generate Stream Info and Validate it ...
+ var stream = await GetFileDescriptor(id);
+ if (stream.IsNull())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Result Model ...
+ var result = new PhysicalFileResult(
+ stream.Path,
+ stream.MIMEType
+ )
+ {
+ FileDownloadName = stream.Name
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Download Specified File ...
+ ///
+ ///
+ ///
+ public async Task Download(string fileName)
+ {
+ //
+ // Validate Args ...
+ var isValid = !fileName.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Generate Stream Info and Validate it ...
+ var stream = await GetFileDescriptor(fileName);
+ if (stream.IsNull())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Result Model ...
+ var result = new PhysicalFileResult(
+ stream.Path,
+ stream.MIMEType
+ )
+ {
+ FileDownloadName = stream.Name
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Upload Files ...
+ ///
+ ///
+ ///
+ ///
+ public async Task> Upload(
+ IFormFileCollection files,
+ XUserClaimsInfoDto userInfo = null
+ )
+ {
+ //
+ // Validate Args ...
+ var isValid = !files.IsNull() &&
+ files.HasChild() &&
+ !userInfo.IsNullOrDefault();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Save Files On Server Side Physically ...
+ // and Validate it ...
+ var uploadResults = await StorageProvider.HandleFilesSave(files);
+ isValid = uploadResults.HasChild();
+ if (!isValid)
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ // Prepare Result ...
+ var entities = new List();
+ foreach (var ur in uploadResults)
+ {
+ //
+ var fileType = StorageProvider.GetFileType(ur.FileName);
+
+ //
+ // Create Entity Model ...
+ var entity = new XFile
+ {
+ Type = fileType,
+ FileName = ur.Name,
+ Name = ur.FileName,
+ Path = ur.FilePath,
+ Thumb = ur.Thmbnail,
+ OwnerId = userInfo.UserId,
+ ThumbPath = ur.ThmbnailPath,
+ UploadedOn = DateTime.UtcNow,
+ };
+
+ //
+ try
+ {
+ //
+ // Add Entity Model to DB ...
+ entity = await FileRepository.AddAsync(entity);
+
+ //
+ if (!entity.IsNullOrDefault())
+ {
+ entities.Add(entity);
+ }
+ }
+ catch { }
+ }
+
+ //
+ // Preparing Result ...
+ var result = await ToXDtoList(entities);
+
+ //
+ return result;
+ }
+
+ ///
+ /// Remove Specified Files ...
+ ///
+ ///
+ ///
+ public async Task> Remove(
+ string ids,
+ XUserClaimsInfoDto userInfo = null
+ )
+ {
+ //
+ // Validate Args ...
+ var isValid = !ids.IsNullOrEmpty() &&
+ !userInfo.IsNullOrDefault();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Parse ID(s) List ...
+ var idsList = ids.ParseListGuid();
+ isValid = !idsList.IsNull() &&
+ idsList.HasChild();
+ if (!isValid)
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ // Loop Through Parsed Ids and Try to Remove ...
+ var result = new List();
+ foreach (var id in idsList)
+ {
+ //
+ // Retrieve XFileDto and Validate it ...
+ var model = await Get(id);
+ isValid = !model.IsNull() && !model.Id.IsNull() && !model.Id.IsDefaultGuid();
+ if (!isValid)
+ {
+ continue;
+ }
+
+ //
+ // Check Physical File Exists or not ...
+ var fileFullPath = StorageProvider.GetFileFullPath(model.Name);
+ var thumbFullPath = model.Thumb.IsNullOrEmpty()
+ ? ""
+ : StorageProvider.GetThumbnailFileFullPath(model.Thumb);
+ var isFileExists = StorageProvider.IsFileExists(fileFullPath);
+ var isThumbExists = model.Thumb.IsNullOrEmpty()
+ ? false
+ : StorageProvider.IsFileExists(thumbFullPath);
+
+ //
+ // Remove Physical Thumbnail File ...
+ if (isThumbExists)
+ {
+ //
+ try
+ {
+ //
+ StorageProvider.DeleteFile(
+ fileFullPath: thumbFullPath,
+ forceFileExists: false
+ );
+ }
+ catch { }
+ }
+
+ //
+ // Remove Pgysical File ...
+ if (isFileExists)
+ {
+ //
+ try
+ {
+ //
+ StorageProvider.DeleteFile(
+ fileFullPath: fileFullPath,
+ forceFileExists: false
+ );
+ }
+ catch { }
+ }
+
+ //
+ // Remove File Entty ...
+ await FileRepository.RemoveAsync(model.Id);
+ result.Add(model.Id);
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Retrieve Specified File Streaming Info ...
+ ///
+ ///
+ ///
+ public async Task GetFileDescriptor(Guid id)
+ {
+ //
+ // Check File Model Exists or not ...
+ var isExists = await IsExists(
+ id: id
+ );
+ if (!isExists)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Retrieve Entity and Validate it ...
+ var entity = await Get(
+ id: id
+ );
+ if (entity.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Physical File Path and Validate it ...
+ var fileFullPath = StorageProvider.GetFileFullPath(entity.Name);
+ isExists = StorageProvider.IsFileExists(fileFullPath);
+ var filePath = StorageProvider.FilePathResolver(fileFullPath);
+ filePath = Path.Combine("wwwroot", filePath);
+ if (!isExists)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Physical File Info ...
+ IFileInfo fileInfo = StorageProvider.FileProvider.GetFileInfo(filePath);
+
+ //
+ // Prepare Default Streaming Requirements ...
+ var mimeType = "application/octetstream";
+ var readStream = fileInfo.CreateReadStream();
+ var fileMimeProvider = new FileExtensionContentTypeProvider();
+ var fileName = entity.Name;
+
+ //
+ // Try to Find Physical File's Content Type ...
+ fileMimeProvider.TryGetContentType(filePath, out mimeType);
+
+ //
+ // Prepare Result Model ...
+ var result = new XFileStreamDescriptorDto
+ {
+ Stream = readStream,
+ MIMEType = mimeType,
+ Name = fileName,
+ Path = fileFullPath
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Retrieve Specified File Streaming Info ...
+ ///
+ ///
+ ///
+ public async Task GetFileDescriptor(string fileName)
+ {
+ //
+ if (fileName.IsNullOrEmpty())
+ {
+ XException.InvalidArgs.Throw();
+ }
+ var entity = await FindOne(e =>
+ e.Name.Contains(fileName) ||
+ e.Path.Contains(fileName) ||
+ e.Thumb.Contains(fileName) ||
+ e.FileName.Contains(fileName) ||
+ e.ThumbPath.Contains(fileName)
+ );
+ var isExists = !entity.IsNullOrDefault();
+ if (!isExists)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Extract File Name ...
+ fileName = Path.GetFileName(fileName);
+
+ //
+ // Check File is Thumbnail or File ...
+ var isThumb = fileName.StartsWith(StorageProvider.Configuration.ThumbPrefix);
+ var isFile = fileName.StartsWith(StorageProvider.Configuration.FilePrefix);
+
+ //
+ // Check File Type is Valid ...
+ isExists = isThumb || isFile;
+ if (!isExists)
+ {
+ XException.UnsupportedFileType.Throw();
+ }
+
+ //
+ // Extract File Full Path ...
+ var fileFullPath = "";
+ if (isThumb)
+ {
+ fileFullPath = StorageProvider.GetThumbnailFileFullPath(fileName);
+ }
+ else
+ {
+ fileFullPath = StorageProvider.GetFileFullPath(fileName);
+ }
+
+ //
+ // Check Physical File Exists or Not ...
+ isExists = StorageProvider.IsFileExists(fileFullPath);
+ if (!isExists)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Generate Physical File Info ...
+ var filePath = StorageProvider.FilePathResolver(fileFullPath);
+ filePath = Path.Combine("wwwroot", filePath);
+ IFileInfo fileInfo = StorageProvider.FileProvider.GetFileInfo(filePath);
+
+ //
+ // Prepare Default Streaming Requirements ...
+ var mimeType = "application/octetstream";
+ var readStream = fileInfo.CreateReadStream();
+ var fileMimeProvider = new FileExtensionContentTypeProvider();
+
+ //
+ // Try to Find Physical File's Content Type ...
+ fileMimeProvider.TryGetContentType(filePath, out mimeType);
+
+ //
+ // Prepare Result Model ...
+ var result = new XFileStreamDescriptorDto
+ {
+ Stream = readStream,
+ MIMEType = mimeType,
+ Name = fileName,
+ Path = fileFullPath
+ };
+
+ //
+ return result;
+ }
+ #endregion
+
+ //
+ #region Data Model ...
+ ///
+ /// Get Specified File Model ...
+ ///
+ ///
+ ///
+ ///
+ public async Task Get(
+ Guid id
+ )
+ {
+ //
+ // Validate ...
+ if (id.IsNull() || id.IsDefaultGuid())
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ var entitiy = await FileRepository.GetAsync(id);
+ if (entitiy.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var result = await ToXFileDto(entitiy);
+ if (result.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Get All Exists File Models ...
+ ///
+ ///
+ ///
+ public async Task> GetAll()
+ {
+ //
+ var result = new List();
+
+ //
+ var entities = await FileRepository.GetAllAsync();
+ if (!entities.IsNull() && entities.HasChild())
+ {
+ //
+ result = (await ToXDtoList(entities))
+ .ToList();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// find an Entity by providing a Conditional Expression ...
+ ///
+ ///
+ public async Task FindOne(Expression> whereClause)
+ {
+ //
+ var result = new XFileDto();
+
+ //
+ var entity = await FileRepository.FindOneAsync(whereClause);
+ if (!entity.IsNullOrDefault())
+ {
+ result = await ToXFileDto(entity);
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// find a collection of Entities by proving a Conditional Expression ...
+ ///
+ ///
+ ///
+ public async Task> FindMany(
+ Expression> whereClause
+ )
+ {
+ //
+ var result = new List();
+
+ //
+ var entities = await FileRepository.FindManyAsync(whereClause);
+ if (!entities.IsNull() && entities.HasChild())
+ {
+ //
+ result = (await ToXDtoList(entities))
+ .ToList();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// retrieve Entities based on XQuery Pagination structure ...
+ ///
+ ///
+ ///
+ public async Task> Query(
+ XQuery query
+ )
+ {
+ //
+ var result = new XQueryResult();
+
+ //
+ var queryResult = await FileRepository.QueryAsync(query);
+ if (!queryResult.IsNullOrDefault())
+ {
+ result = await ToXDtoQueryResult(queryResult);
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// retrieve Entities based on XQuery Pagination structure by providing a Conditional Expression ...
+ ///
+ ///
+ ///
+ ///
+ public async Task> ConditionalQuery(
+ Expression> whereClause,
+ XQuery query
+ )
+ {
+ //
+ var result = new XQueryResult();
+
+ //
+ var queryResult = await FileRepository.ConditionalQueryAsync(
+ query: query,
+ whereClause: whereClause
+ );
+ if (!queryResult.IsNullOrDefault())
+ {
+ result = await ToXDtoQueryResult(queryResult);
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Update an Entity values ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task Update(
+ Guid id,
+ XFileDto item,
+ XUserClaimsInfoDto userInfo = null
+ )
+ {
+ //
+ // Validate ...
+ bool isValid = !id.IsNull() &&
+ !id.IsDefaultGuid() &&
+ !item.IsNullOrDefault() &&
+ !userInfo.IsNullOrDefault();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Entitiy Exists and Retrieve it ...
+ isValid = await IsExists(id);
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var entity = await FileRepository.GetAsync(id);
+ if (entity.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Fill Data for Update ...
+ entity = entity.UpdateData(
+ updateWith: item,
+ propertyBlackList: new List
+ {
+ nameof(XFile.Id),
+ nameof(XFile.Deleted),
+ nameof(XFileDto.Owner)
+ }
+ );
+ if (entity.IsNullOrDefault())
+ {
+ XException.InvalidData.Throw();
+ }
+
+ //
+ entity = await FileRepository.UpdateAsync(id, entity);
+ if (entity.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ // Validate Action ...
+ isValid =
+ entity.OwnerId == userInfo.UserId ||
+ userInfo.Roles.Any(r => r.ToNormalString() == "admin".ToNormalString());
+ if (!isValid)
+ {
+ XException.NotAllowed.Throw();
+ }
+
+ //
+ var result = await ToXFileDto(entity);
+
+ //
+ return result;
+ }
+
+ ///
+ /// remove an Entity ...
+ ///
+ ///
+ ///
+ ///
+ public async Task Remove(
+ Guid id,
+ XUserClaimsInfoDto userInfo = null
+ )
+ {
+ //
+ // Validate ...
+ var isValid = !id.IsNull() &&
+ !id.IsDefaultGuid() &&
+ !userInfo.IsNullOrDefault();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Entity Exists and Retrieve it ...
+ isValid = await IsExists(id);
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var result = await Get(id);
+ isValid = !result.IsNullOrDefault();
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Validate Action ...
+ isValid =
+ result.OwnerId == userInfo.UserId ||
+ userInfo.Roles.Any(r => r.ToNormalString() == "admin".ToNormalString());
+ if (!isValid)
+ {
+ XException.NotAllowed.Throw();
+ }
+
+ //
+ var entitiy = await FileRepository.RemoveAsync(id);
+ if (entitiy.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ result = await ToXFileDto(entitiy);
+ if (result.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// count all exists Entities ...
+ ///
+ ///
+ public async Task Count()
+ {
+ return await FileRepository.CountAsync();
+ }
+
+ ///
+ /// Check an Entity exists or not ...
+ ///
+ ///
+ ///
+ public async Task IsExists(
+ Guid id
+ )
+ {
+ return await FileRepository.IsExistsAsync(id);
+ }
+ #endregion
+
+ //
+ #region Helpers ...
+ ///
+ /// Converts an Entity to Dto ...
+ ///
+ ///
+ ///
+ public async Task ToXFileDto(XFile model)
+ {
+ //
+ XFileDto result = null;
+
+ //
+ if (!model.IsNullOrDefault())
+ {
+ //
+ result = model.ToXFileDto();
+
+ //
+ // Prepare Inner API Providers Device Dto ...
+ var device = IdentityProvider.GetDevice();
+ var userInfo = await IdentityProvider.GetUserInfo(
+ device: device,
+ userSelectByParam: model.OwnerId
+ );
+ if (userInfo.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ result.Owner = userInfo.ToXPersonDto();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Convert a List of Entities to Dto ...
+ ///
+ ///
+ ///
+ public async Task> ToXDtoList(IEnumerable list)
+ {
+ //
+ var result = new List();
+
+ //
+ if (!list.IsNull() && list.HasChild())
+ {
+ //
+ foreach (var item in list)
+ {
+ //
+ var dto = await ToXFileDto(item);
+ if (!dto.IsNullOrDefault())
+ {
+ result.Add(dto);
+ }
+ }
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Converts an Entity Query Result to Dto ...
+ ///
+ ///
+ ///
+ public async Task> ToXDtoQueryResult(XQueryResult queryResult)
+ {
+ //
+ var result = new XQueryResult();
+
+ //
+ if (!queryResult.IsNullOrDefault())
+ {
+ //
+ result.Page = queryResult.Page;
+ result.PageSize = queryResult.PageSize;
+ result.TotalItems = queryResult.TotalItems;
+ result.TotalPages = queryResult.TotalPages;
+ result.TotalFilteredItems = queryResult.TotalFilteredItems;
+ result.TotalFilteredPages = queryResult.TotalFilteredPages;
+
+ //
+ if (!queryResult.Items.IsNull() && queryResult.Items.HasChild())
+ {
+ result.Items = await ToXDtoList(queryResult.Items);
+ }
+ }
+
+ //
+ return result;
+ }
+ #endregion
+ }
+}
\ No newline at end of file