public async Task <GuestInvite> CreateGuestInviteAsync(GuestInvite model) { var validationResult = _validatorLocator.Validate <GuestInviteValidator>(model); if (!validationResult.IsValid) { throw new ValidationFailedException(validationResult.Errors); } // Get dependent resources var projectTask = GetProjectAsync(model.ProjectId); var invitedByUserTask = GetUserAsync(model.InvitedBy); await Task.WhenAll(projectTask, invitedByUserTask); var project = projectTask.Result; var invitedByUser = invitedByUserTask.Result; var accessCode = await GetGuestAccessCodeAsync(project); model.Id = model.Id == Guid.Empty ? Guid.NewGuid() : model.Id; model.CreatedDateTime = DateTime.UtcNow; model.ProjectAccessCode = accessCode; model.ProjectTenantId = project.TenantId; var result = await _guestInviteRepository.CreateItemAsync(model); // Delete all prior guest invites with the same email and ProjectId as the session just created. await _guestInviteRepository.DeleteItemsAsync(x => x.ProjectId == model.ProjectId && x.GuestEmail == model.GuestEmail && x.Id != result.Id); _eventService.Publish(EventNames.GuestInviteCreated, result); // Send an invite email to the guest var emailResult = await _emailSendingService.SendGuestInviteEmailAsync(project.Name, project.ProjectUri, model.GuestEmail, invitedByUser.FirstName); if (!emailResult.IsSuccess()) { _logger.Error($"Sending guest invite email failed. Reason={emailResult.ReasonPhrase} Error={_serializer.SerializeToString(emailResult.ErrorResponse)}"); await _guestInviteRepository.DeleteItemAsync(result.Id); } return(result); }