Thanks for registering. Please confirm your email address by clicking the link below:
+ If you did not create an account, you can safely ignore this email.
+ > SendPasswordResetLinkAsync(string email, string resetLink)
+ {
+ string subject = "Reset Your AskFm Password";
+ string body = $@"
+ Password Reset Request
+ We received a request to reset your password. You can reset your password by clicking the link below:
+ Reset My Password
+ If you did not request a password reset, please ignore this email.
+
+ Thank you,
+ The AskFm Team
";
+
+ return await SendEmailAsync(email, subject, body);
+ }
+
+ public async Task> SendPasswordResetCodeAsync( string email, string resetCode)
+ {
+ string subject = "Your AskFm Password Reset Code";
+ string body = $@"
+ Password Reset Code
+ We received a request to reset your password. Use the following code to complete the process:
+ {resetCode}
+ This code will expire shortly. If you did not request a password reset, please ignore this email.
+
+ Thank you,
+ The AskFm Team
";
+
+ return await SendEmailAsync(email, subject, body);
+ }
+
+
+ public async Task> SendEmailAsync(string toEmail, string subject, string htmlMessage)
+ {
+
+ var client = new SmtpClient(_emailSettings.Client, 587)
+ {
+ EnableSsl = true,
+ Credentials = new NetworkCredential(_emailSettings.From, _emailSettings.Password)
+ };
+
+ // Create and send the email
+ await client.SendMailAsync(
+ new MailMessage(from: _emailSettings.From,
+ to: toEmail,
+ subject,
+ htmlMessage
+ ));
+ return await ServiceResult.Success(true);
+ }
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/ICommentLikeService.cs b/AskFm/AskFm.BLL/Services/ICommentLikeService.cs
new file mode 100644
index 0000000..5285cd5
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/ICommentLikeService.cs
@@ -0,0 +1,10 @@
+using AskFm.BLL.DTO;
+
+namespace AskFm.BLL.Services;
+
+public interface ICommentLikeService
+{
+ Task>> GetLikesForCommentAsync(int commentId);
+ Task> AddLikeAsync(int commentId, int userId);
+ Task> DeleteLikeAsync(int commentId, int userId);
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/ICommentService.cs b/AskFm/AskFm.BLL/Services/ICommentService.cs
new file mode 100644
index 0000000..8c58275
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/ICommentService.cs
@@ -0,0 +1,19 @@
+using AskFm.BLL.DTO;
+using AskFm.DAL.Models;
+
+namespace AskFm.BLL.Services;
+
+public interface ICommentService
+{
+ // Get a specific comment by ID
+ Task> GetCommentAsync(int id);
+
+ // Add a comment to a thread
+ Task> AddComment(int threadId, int userId, CreateCommentDto commentDto);
+
+ // Get all comments for a thread with pagination
+ Task>> GetCommentsByThreadId(int threadId, int page, int pageSize);
+
+ // Delete a specific comment
+ Task> DeleteComment(int threadId, int commentId, int userId);
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/IEmailSender.cs b/AskFm/AskFm.BLL/Services/IEmailSender.cs
new file mode 100644
index 0000000..432f1df
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/IEmailSender.cs
@@ -0,0 +1,12 @@
+using AskFm.DAL.Models;
+using Microsoft.AspNetCore.Identity;
+
+namespace AskFm.BLL.Services;
+
+public interface IEmailSender
+{
+ public Task> SendPasswordResetLinkAsync( string email, string resetLink);
+ public Task> SendConfirmationLinkAsync(string email, string confirmationLink);
+ public Task> SendPasswordResetCodeAsync( string email, string resetCode);
+ Task> SendEmailAsync (string email, string subject, string message);
+}
diff --git a/AskFm/AskFm.BLL/Services/INotificationService.cs b/AskFm/AskFm.BLL/Services/INotificationService.cs
new file mode 100644
index 0000000..afa49ad
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/INotificationService.cs
@@ -0,0 +1,13 @@
+using AskFm.BLL.DTO;
+using AskFm.DAL.Enums;
+
+namespace AskFm.BLL.Services;
+
+public interface INotificationService
+{
+ Task>> GetUserNotifications(int userId, int pageNumber = 1, int pageSize = 10);
+ Task>> GetNotificationsByType(int userId, string category, int pageNumber = 1, int pageSize = 10);
+ Task> MarkNotificationAsRead(int notificationId, int userId);
+ Task> MarkAllNotificationsAsRead(int userId);
+ Task> CreateNotification(int userId, NotificationStatus type, int resourceId, string message);
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/IRedisService.cs b/AskFm/AskFm.BLL/Services/IRedisService.cs
new file mode 100644
index 0000000..ae55879
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/IRedisService.cs
@@ -0,0 +1,14 @@
+using Microsoft.Extensions.Caching.Distributed;
+using System.Text.Json;
+
+namespace AskFm.BLL.Services;
+
+public interface IRedisService
+{
+ public Task SetCacheAsync(string key, T value, TimeSpan expirationTime);
+
+ public Task GetCacheAsync(string key);
+
+ public Task RemoveCacheAsync(string key);
+}
+
diff --git a/AskFm/AskFm.BLL/Services/IThreadLikeService.cs b/AskFm/AskFm.BLL/Services/IThreadLikeService.cs
new file mode 100644
index 0000000..156e8d8
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/IThreadLikeService.cs
@@ -0,0 +1,11 @@
+using AskFm.BLL.DTO;
+using Microsoft.AspNetCore.Mvc;
+
+namespace AskFm.BLL.Services;
+
+public interface IThreadLikeService
+{
+ public Task> AddLike(int id, int userId);
+ public Task>> GetLikes(int id);
+ public Task> RemoveLike(int threadId, int userId);
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/IThreadService.cs b/AskFm/AskFm.BLL/Services/IThreadService.cs
new file mode 100644
index 0000000..d329412
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/IThreadService.cs
@@ -0,0 +1,17 @@
+using AskFm.BLL.DTO;
+
+namespace AskFm.BLL.Services;
+
+public interface IThreadService
+{
+ public Task> AddThread(int askerId, CreateThreadDto createThreadDto);
+ public Task> GetThreadById(int id);
+ public Task>> GetAllThreads(int askedId);
+ public Task> AnswerThread(int threadId, int userId, AnswerThreadDto answerDto);
+ public Task>> GetThreads(int page, int pageSize);
+ public Task> DeleteThread(int threadId, int userId);
+ public Task>> GetFeed(int userId, int page, int pageSize);
+ public Task> SaveThread(int threadId, int userId);
+ public Task> UnsaveThread(int threadId, int userId);
+ public Task>> GetSavedThreads(int userId, int page, int pageSize);
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/NotificationService.cs b/AskFm/AskFm.BLL/Services/NotificationService.cs
new file mode 100644
index 0000000..cd3c90b
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/NotificationService.cs
@@ -0,0 +1,210 @@
+using AskFm.BLL.DTO;
+using AskFm.BLL.Hub;
+using AskFm.DAL.Enums;
+using AskFm.DAL.Interfaces;
+using AskFm.DAL.Models;
+using Microsoft.AspNetCore.SignalR;
+
+namespace AskFm.BLL.Services;
+
+public class NotificationService : INotificationService
+{
+ private readonly INotificationRepository _notificationRepository;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly IHubContext _hubContext;
+
+ public NotificationService(INotificationRepository notificationRepository, IUnitOfWork unitOfWork, IHubContext hubContext)
+ {
+ _notificationRepository = notificationRepository;
+ _unitOfWork = unitOfWork;
+ _hubContext = hubContext;
+ }
+
+ public async Task>> GetUserNotifications(int userId, int pageNumber = 1, int pageSize = 10)
+ {
+ try
+ {
+ var (notifications, totalCount) = await _notificationRepository.GetAllNotifications(userId, pageNumber, pageSize);
+
+ var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+ var notificationDtos = new List();
+
+ foreach (var notification in notifications)
+ {
+ var actorUser = await _notificationRepository.GetActorUserByResourceId(notification.ResourceId, notification.Type);
+ notificationDtos.Add(new NotificationDto
+ {
+ Id = notification.Id,
+ UserId = notification.UserId,
+ Type = notification.Type.ToString(),
+ ResourceId = notification.ResourceId,
+ Message = notification.Message,
+ IsRead = notification.IsRead,
+ CreatedAt = notification.CreatedAt,
+ Actor = actorUser == null ? null : new ActorDto
+ {
+ Id = actorUser.Id,
+ Username = actorUser?.UserName ?? "Unknown",
+ AvatarPath = actorUser?.AvatarPath ?? String.Empty
+ },
+ Pagination = new PaginationDto
+ {
+ CurrentPage = pageNumber,
+ TotalPages = totalPages,
+ TotalCount = totalCount,
+ HasNext = pageNumber < totalPages,
+ HasPrevious = pageNumber > 1
+ }
+ });
+ }
+ return await ServiceResult>.Success(notificationDtos);
+ }
+ catch (Exception ex)
+ {
+ return await ServiceResult>.Failure(new List { ex.Message });
+ }
+ }
+
+ public async Task>> GetNotificationsByType(int userId, string category, int pageNumber = 1, int pageSize = 10)
+ {
+ try
+ {
+ // Convert category to uppercase and match with enum
+ if (!Enum.TryParse(category.ToUpper(), out var notificationType))
+ return await ServiceResult>.Failure(new List { $"Invalid notification category: {category}" });
+
+ var (notifications, totalCount) = await _notificationRepository.GetNotificationsByType(userId, notificationType, pageNumber, pageSize);
+
+ var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+ var notificationDtos = new List();
+
+ foreach (var notification in notifications)
+ {
+ var actorUser = await _notificationRepository.GetActorUserByResourceId(notification.ResourceId, notification.Type);
+ notificationDtos.Add(new NotificationDto
+ {
+ Id = notification.Id,
+ UserId = notification.UserId,
+ Type = notification.Type.ToString(),
+ ResourceId = notification.ResourceId,
+ Message = notification.Message,
+ IsRead = notification.IsRead,
+ CreatedAt = notification.CreatedAt,
+ Actor = actorUser == null ? null : new ActorDto
+ {
+ Id = actorUser.Id,
+ Username = actorUser?.UserName ?? "Unknown",
+ AvatarPath = actorUser?.AvatarPath ?? String.Empty
+ },
+ Pagination = new PaginationDto
+ {
+ CurrentPage = pageNumber,
+ TotalPages = totalPages,
+ TotalCount = totalCount,
+ HasNext = pageNumber < totalPages,
+ HasPrevious = pageNumber > 1
+ }
+ });
+ }
+
+ return await ServiceResult>.Success(notificationDtos);
+ }
+ catch (Exception ex)
+ {
+ return await ServiceResult>.Failure(new List { ex.Message });
+ }
+ }
+
+ public async Task> MarkNotificationAsRead(int notificationId, int userId)
+ {
+ try
+ {
+ var notification = await _notificationRepository.GetUserNotificationById(notificationId, userId);
+ if (notification == null)
+ return await ServiceResult.Failure(new List { "Notification not found or access denied." });
+
+ notification.IsRead = true;
+ _unitOfWork.Notifications.Update(notification);
+ await _unitOfWork.SaveAsync();
+
+ return await ServiceResult.Success("notification has been read");
+ }
+ catch (Exception ex)
+ {
+ return await ServiceResult.Failure(new List { ex.Message });
+ }
+ }
+
+ public async Task> MarkAllNotificationsAsRead(int userId)
+ {
+ try
+ {
+ var unreadNotifications = await _unitOfWork.Notifications.FindAllAsync(n => n.UserId == userId && !n.IsRead);
+
+ foreach (var notification in unreadNotifications)
+ {
+ notification.IsRead = true;
+ _unitOfWork.Notifications.Update(notification);
+ }
+
+ await _unitOfWork.SaveAsync();
+ return await ServiceResult.Success("All notifications marked as read");
+ }
+ catch (Exception ex)
+ {
+ return await ServiceResult.Failure(new List { ex.Message });
+ }
+ }
+
+ public async Task> CreateNotification(int userId, NotificationStatus type, int resourceId, string message)
+ {
+ try
+ {
+ var notification = new Notification
+ {
+ UserId = userId,
+ Type = type,
+ ResourceId = resourceId,
+ Message = message,
+ IsRead = false,
+ CreatedAt = DateTime.UtcNow,
+ UpdatedAt = DateTime.UtcNow
+ };
+
+ await _unitOfWork.Notifications.AddAsync(notification);
+ await _unitOfWork.SaveAsync();
+
+ // Get actor information for the notification
+ var actorUser = await _notificationRepository.GetActorUserByResourceId(resourceId, type);
+
+ var notificationDto = new NotificationDto
+ {
+ Id = notification.Id,
+ UserId = notification.UserId,
+ Type = notification.Type.ToString(),
+ ResourceId = notification.ResourceId,
+ Message = notification.Message,
+ IsRead = notification.IsRead,
+ CreatedAt = notification.CreatedAt,
+ Actor = actorUser == null ? null : new ActorDto
+ {
+ Id = actorUser.Id,
+ Username = actorUser.UserName ?? "Unknown",
+ AvatarPath = actorUser.AvatarPath ?? string.Empty
+ }
+ };
+
+ // Send real-time notification to the specific user
+ await _hubContext.Clients.Group($"user_{userId}")
+ .SendAsync("ReceiveNotification", notificationDto);
+
+ return await ServiceResult.Success(notificationDto);
+ }
+ catch (Exception ex)
+ {
+ return await ServiceResult.Failure(new List { ex.Message });
+ }
+ }
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/RedisCacheService.cs b/AskFm/AskFm.BLL/Services/RedisCacheService.cs
new file mode 100644
index 0000000..0c95a83
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/RedisCacheService.cs
@@ -0,0 +1,37 @@
+using Microsoft.Extensions.Caching.Distributed;
+using System.Text.Json;
+
+namespace AskFm.BLL.Services;
+
+public class RedisCacheService : IRedisService
+{
+ private readonly IDistributedCache _cache;
+
+ public RedisCacheService(IDistributedCache cache)
+ {
+ _cache = cache;
+ }
+
+ public async Task SetCacheAsync(string key, T value, TimeSpan expirationTime)
+ {
+ var options = new DistributedCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = expirationTime
+ };
+
+ var jsonData = JsonSerializer.Serialize(value);
+ await _cache.SetStringAsync(key, jsonData, options);
+ }
+
+ public async Task GetCacheAsync(string key)
+ {
+ var jsonData = await _cache.GetStringAsync(key);
+ return jsonData is null ? default : JsonSerializer.Deserialize(jsonData);
+ }
+
+ public async Task RemoveCacheAsync(string key)
+ {
+ await _cache.RemoveAsync(key);
+ }
+}
+
diff --git a/AskFm/AskFm.BLL/Services/ServiceResult.cs b/AskFm/AskFm.BLL/Services/ServiceResult.cs
new file mode 100644
index 0000000..74c8c58
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/ServiceResult.cs
@@ -0,0 +1,33 @@
+namespace AskFm.BLL.Services;
+
+public class ServiceResult
+{
+ public bool success { get; set; }
+ public List? Errors { get; set; }
+ public T? Data { get; set; }
+
+ public static async Task> Success(T data)
+ {
+ return new ServiceResult
+ {
+ success = true,
+ Data = data
+ };
+ }
+ public static async Task> Success()
+ {
+ return new ServiceResult
+ {
+ success = true,
+ };
+ }
+
+ public static async Task> Failure(List errors)
+ {
+ return new ServiceResult
+ {
+ success = false,
+ Errors = errors
+ };
+ }
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/ThreadLikeService.cs b/AskFm/AskFm.BLL/Services/ThreadLikeService.cs
new file mode 100644
index 0000000..27facb4
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/ThreadLikeService.cs
@@ -0,0 +1,203 @@
+using AskFm.BLL.DTO;
+using AskFm.DAL.Interfaces;
+using AskFm.DAL.Models;
+using AutoMapper;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+
+namespace AskFm.BLL.Services;
+
+public class ThreadLikeService : IThreadLikeService
+{
+ private IUnitOfWork _unitOfWork;
+ private readonly ILogger _logger;
+ private readonly IMapper _mapper;
+
+ public ThreadLikeService(IUnitOfWork unitOfWork, ILogger logger, IMapper mapper)
+ {
+ _unitOfWork = unitOfWork;
+ _logger = logger;
+ _mapper = mapper;
+ }
+
+ // add a like on the Thread that has id = id
+ public async Task> AddLike(int id, int userId)
+ {
+ try
+ {
+ var transaction = await _unitOfWork.BeginTransactionAsync();
+ // get the thread, Including the ThreadLike Collection
+ var thread = await _unitOfWork.Threads.FindAsync(
+ predicate: thread => thread.Id == id,
+ includes: new[] { "ThreadLikes" }
+ );
+
+ // check if thread exists
+ if (thread == null)
+ {
+ await transaction.RollbackAsync();
+ return await ServiceResult.Failure(new List() { "Thread not found" });
+ }
+
+ // check if user has already liked this thread
+ var existingLike = thread.ThreadLikes?.FirstOrDefault(like => like.UserId == userId);
+ if (existingLike != null)
+ {
+ // if the The use already liked this thread
+ if (!existingLike.IsDeleted)
+ {
+ var errors = new List()
+ {
+ "User has already liked this thread"
+ };
+ await transaction.RollbackAsync();
+ return await ServiceResult.Failure(errors);
+ }
+
+ // otherwise , the user liked the comment , then unliked it , and then wants to like it again
+ existingLike.IsDeleted = false;
+ existingLike.CreatedAt = DateTime.UtcNow;
+ thread.ThreadLikes.Add(existingLike);
+ _unitOfWork.Threads.Update(thread);
+ await _unitOfWork.SaveAsync();
+ await transaction.CommitAsync();
+
+ _logger.LogInformation("Like added successfully for thread id: {threadId}", thread.Id);
+
+
+ // updating the createdAt column to Now , ignoring the first time the user liked the comment
+ return await ServiceResult.Success(new ThreadLikeResponseDto()
+ {
+ ThreadId = existingLike.ThreadId,
+ UserId = existingLike.UserId,
+ CreatedAt = existingLike.CreatedAt
+ });
+ }
+
+
+ try
+ {
+ // create a new ThreadLike
+ var threadLike = new ThreadLike
+ {
+ ThreadId = id,
+ UserId = userId,
+ CreatedAt = DateTime.UtcNow
+ };
+
+ // add the ThreadLike to the Thread
+ thread.ThreadLikes?.Add(threadLike);
+
+ // update the thread
+ await _unitOfWork.Threads.UpdateAsync(thread);
+ await _unitOfWork.SaveAsync();
+
+ await transaction.CommitAsync();
+
+ // create and return the response DTO
+ var response = new ThreadLikeResponseDto
+ {
+ ThreadId = threadLike.ThreadId,
+ UserId = threadLike.UserId,
+ CreatedAt = threadLike.CreatedAt
+ };
+
+ return await ServiceResult.Success(response);
+ }
+ catch (Exception e)
+ {
+ await transaction.RollbackAsync();
+ throw;
+ }
+ }
+ catch (Exception e)
+ {
+ return await ServiceResult.Failure(new List() { e.Message });
+ }
+ }
+
+ public async Task>> GetLikes(int id)
+ {
+ try
+ {
+ // get the thread, Including the ThreadLikes collection
+ var thread = await _unitOfWork.Threads.FindAsync(
+ predicate: thread => thread.Id == id,
+ includes: new[] { "ThreadLikes.User" }
+ );
+
+ // check if thread exists
+ if (thread == null)
+ {
+ return await ServiceResult>.Failure(new List()
+ { "Thread not found" });
+ }
+
+ // return the list of likes
+ var likes = thread.ThreadLikes.Select(like => new ThreadLikeResponseDto
+ {
+ ThreadId = like.ThreadId,
+ UserId = like.UserId,
+ UserName = like.User?.Name ?? "Unknown",
+ CreatedAt = like.CreatedAt
+ }).ToList();
+
+ return await ServiceResult>.Success(likes);
+ }
+ catch (Exception e)
+ {
+ return await ServiceResult>.Failure(new List() { e.Message });
+ }
+ }
+
+ // Remove a like from the thread with id = threadId
+ public async Task> RemoveLike(int threadId, int userId)
+ {
+ try
+ {
+ // get the thread with its likes
+ var thread = await _unitOfWork.Threads.FindAsync(
+ predicate: thread => thread.Id == threadId,
+ includes: new[] { "ThreadLikes" }
+ );
+
+ // check if thread exists
+ if (thread == null)
+ {
+ return await ServiceResult.Failure(new List() { "Thread not found" });
+ }
+
+ // find the like to remove
+ var likeToRemove = thread.ThreadLikes?.FirstOrDefault(like => like.UserId == userId);
+ if (likeToRemove == null)
+ {
+ return await ServiceResult.Failure(new List() { "Like not found for this user" });
+ }
+
+ var transaction = await _unitOfWork.BeginTransactionAsync();
+
+ try
+ {
+ // remove the like from the thread
+ thread.ThreadLikes?.Remove(likeToRemove);
+
+ // update the thread
+ await _unitOfWork.Threads.UpdateAsync(thread);
+ await _unitOfWork.SaveAsync();
+
+ transaction.Commit();
+
+ return await ServiceResult.Success(true);
+ }
+ catch (Exception e)
+ {
+ await transaction.RollbackAsync();
+ throw;
+ }
+ }
+ catch (Exception e)
+ {
+ return await ServiceResult.Failure(new List() { e.Message });
+ }
+ }
+}
\ No newline at end of file
diff --git a/AskFm/AskFm.BLL/Services/ThreadService.cs b/AskFm/AskFm.BLL/Services/ThreadService.cs
new file mode 100644
index 0000000..77cb2a7
--- /dev/null
+++ b/AskFm/AskFm.BLL/Services/ThreadService.cs
@@ -0,0 +1,570 @@
+using AskFm.BLL.DTO;
+using AskFm.DAL.Enums;
+using AskFm.DAL.Interfaces;
+using AskFm.DAL.Models;
+using AutoMapper;
+using Microsoft.Extensions.Logging;
+using Thread = AskFm.DAL.Models.Thread;
+
+namespace AskFm.BLL.Services;
+
+public class ThreadService : IThreadService
+{
+ private IUnitOfWork _unitOfWork;
+ private readonly ILogger _logger;
+ private readonly IMapper _mapper;
+
+ public ThreadService(IUnitOfWork unitOfWork, ILogger logger, IMapper mapper)
+ {
+ _unitOfWork = unitOfWork;
+ _logger = logger;
+ _mapper = mapper;
+ }
+
+ public async Task> AddThread(int askerId, CreateThreadDto createThreadDto)
+ {
+ var transaction = await _unitOfWork.BeginTransactionAsync();
+
+ try
+ {
+ // check if the Asked user exite or not
+ var askedId = createThreadDto.AskedId;
+
+ var askedUser = await _unitOfWork.Users.GetByIdAsync(askedId);
+ if (askedUser == null)
+ {
+ await transaction.RollbackAsync();
+ return await ServiceResult.Failure(
+ new List() { "Could not find asked user" });
+ }
+
+ // getting the Asker user object
+ var askerUser = await _unitOfWork.Users.GetByIdAsync(askerId);
+ if (askerUser == null)
+ {
+ await transaction.RollbackAsync();
+ return await ServiceResult.Failure(
+ new List() { "Could not find asker user" });
+ }
+
+
+ // check if the Asked User's id == Asker User's Id
+ if (askedId == askerId)
+ {
+ await transaction.RollbackAsync();
+ return await ServiceResult.Failure(
+ new List() { "User can not ask him self" });
+ }
+
+
+ // check if the QuestionContent is empty or not
+ if (string.IsNullOrEmpty(createThreadDto.QuestionContent))
+ {
+ await transaction.RollbackAsync();
+ return await ServiceResult