From a15b25248d08170667c39ec3e661540d1c1e307b Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 11 Sep 2026 10:32:51 +0200 Subject: [PATCH] Improved results handling in service layer --- .../Communications/CommunicationsService.cs | 10 +++--- .../Services/Evidence/EvidenceService.cs | 21 ++++++------ .../Services/Execution/ExecutionService.cs | 20 +++++------ .../Services/Governance/GovernanceService.cs | 18 +++++----- .../Services/Grants/GrantsService.cs | 23 ++++++------- .../Services/Projects/ProjectService.cs | 34 ++++++++----------- .../Shared/BrowserLocalStorageService.cs | 12 +++---- .../Services/Shared/HashService.cs | 33 +++++++++--------- .../Services/Shared/IdentityService.cs | 2 +- .../Services/Shared/TokenService.cs | 8 ++--- .../Services/Users/UserService.cs | 9 +++-- 11 files changed, 87 insertions(+), 103 deletions(-) diff --git a/PostFundManagement.Application/Services/Communications/CommunicationsService.cs b/PostFundManagement.Application/Services/Communications/CommunicationsService.cs index 129909e..3cdf506 100644 --- a/PostFundManagement.Application/Services/Communications/CommunicationsService.cs +++ b/PostFundManagement.Application/Services/Communications/CommunicationsService.cs @@ -38,9 +38,8 @@ public sealed class CommunicationsService(IDbContextFactory 0 - ? Result.Ok(invite.Map()) - : Result.Fail(CreateError.New); + return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New) + .ToResult(invite.Map()); })); public async ValueTask> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -64,9 +63,8 @@ public sealed class CommunicationsService(IDbContextFactory i.Recipient == applicantUserId, cancellationToken); - return invite is not null - ? Result.Ok(invite.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(invite is null, NotFoundError.New) + .ToResult(invite!.Map()); })); public async ValueTask> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) => diff --git a/PostFundManagement.Application/Services/Evidence/EvidenceService.cs b/PostFundManagement.Application/Services/Evidence/EvidenceService.cs index e5558dd..de6712c 100644 --- a/PostFundManagement.Application/Services/Evidence/EvidenceService.cs +++ b/PostFundManagement.Application/Services/Evidence/EvidenceService.cs @@ -47,7 +47,7 @@ public sealed class EvidenceService(IDbContextFactory cont context.Evidences.Add(evidence); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default) => @@ -66,7 +66,7 @@ public sealed class EvidenceService(IDbContextFactory cont .SetProperty(f => f.ActualAmount, amount) .SetProperty(f => f.CreatedBy, userId), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); public async ValueTask> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -119,7 +119,8 @@ public sealed class EvidenceService(IDbContextFactory cont CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.Create("No record could be created.")); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, + CreateError.Create("No record could be created.")); })); public async ValueTask CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -142,7 +143,7 @@ public sealed class EvidenceService(IDbContextFactory cont CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken) => @@ -158,9 +159,8 @@ public sealed class EvidenceService(IDbContextFactory cont var indicator = await context.Indicators.AsNoTracking().FirstOrDefaultAsync(i => i.Id == decodeResult.Value, cancellationToken); - return indicator is not null - ? Result.Ok(indicator.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(indicator is null, NotFoundError.New) + .ToResult(indicator!.Map()); })); public async ValueTask> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) => @@ -176,9 +176,8 @@ public sealed class EvidenceService(IDbContextFactory cont var evidence = await context.Evidences.AsNoTracking().FirstOrDefaultAsync(e => e.Id == decodeResult.Value, cancellationToken); - return evidence is not null - ? Result.Ok(evidence.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(evidence is null, NotFoundError.New) + .ToResult(evidence!.Map()); })); public async ValueTask> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => @@ -237,6 +236,6 @@ public sealed class EvidenceService(IDbContextFactory cont .SetProperty(f => f.UpdatedBy, userId) .SetProperty(f => f.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); } diff --git a/PostFundManagement.Application/Services/Execution/ExecutionService.cs b/PostFundManagement.Application/Services/Execution/ExecutionService.cs index 8d122fd..952a32d 100644 --- a/PostFundManagement.Application/Services/Execution/ExecutionService.cs +++ b/PostFundManagement.Application/Services/Execution/ExecutionService.cs @@ -57,7 +57,7 @@ public sealed class ExecutionService(IDbContextFactory con CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -78,7 +78,7 @@ public sealed class ExecutionService(IDbContextFactory con CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) => @@ -98,7 +98,7 @@ public sealed class ExecutionService(IDbContextFactory con .SetProperty(f => f.UpdatedBy, userId) .SetProperty(f => f.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); public async ValueTask> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken) => @@ -115,9 +115,8 @@ public sealed class ExecutionService(IDbContextFactory con var disbursement = await context.Disbursements.AsNoTracking() .FirstOrDefaultAsync(d => d.Id == decodeResult.Value, cancellationToken); - return disbursement is not null - ? Result.Ok(disbursement.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(disbursement is null, NotFoundError.New) + .ToResult(disbursement!.Map()); })); public async ValueTask> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) => @@ -134,9 +133,8 @@ public sealed class ExecutionService(IDbContextFactory con var risk = await context.Risks.AsNoTracking() .FirstOrDefaultAsync(r => r.Id == decodeResult.Value, cancellationToken); - return risk is not null - ? Result.Ok(risk.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(risk is null, NotFoundError.New) + .ToResult(risk!.Map()); })); public async ValueTask UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) => @@ -152,7 +150,7 @@ public sealed class ExecutionService(IDbContextFactory con .SetProperty(u => u.Likelihood, request.Likelihood) .SetProperty(u => u.Impact, request.Impact), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); public async ValueTask UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -168,6 +166,6 @@ public sealed class ExecutionService(IDbContextFactory con .SetProperty(d => d.UpdatedAt, DateTime.UtcNow) .SetProperty(d => d.UpdatedBy, userId), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); } diff --git a/PostFundManagement.Application/Services/Governance/GovernanceService.cs b/PostFundManagement.Application/Services/Governance/GovernanceService.cs index bbf8d6a..53e1e03 100644 --- a/PostFundManagement.Application/Services/Governance/GovernanceService.cs +++ b/PostFundManagement.Application/Services/Governance/GovernanceService.cs @@ -77,9 +77,8 @@ public sealed class GovernanceService(IDbContextFactory co var organisation = await context.Organisations.AsNoTracking() .FirstOrDefaultAsync(o => o.Id == decodeResult.Value, cancellationToken); - return organisation is not null - ? Result.Ok(organisation.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(organisation is null, NotFoundError.New) + .ToResult(organisation!.Map()); })); public async ValueTask> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) => @@ -148,7 +147,7 @@ public sealed class GovernanceService(IDbContextFactory co CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default) => @@ -164,7 +163,7 @@ public sealed class GovernanceService(IDbContextFactory co .SetProperty(u => u.Email, request.Email.ToLower(CultureInfo.InvariantCulture).Clean()) .SetProperty(u => u.Type, request.Type), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); public async ValueTask CreatePortfolioAsync(CreatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -193,7 +192,7 @@ public sealed class GovernanceService(IDbContextFactory co Description = request.Description.Humanize(LetterCasing.Sentence).Trim() }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask UpdatePortfolioAsync(UpdatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -211,7 +210,7 @@ public sealed class GovernanceService(IDbContextFactory co .SetProperty(u => u.OwnedBy, request.OwnerId) .SetProperty(u => u.Description, request.Description.Humanize(LetterCasing.Sentence).Trim()), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.Create("Nothing was saved, no change detected.")); + return Result.OkIf(changedTotal > 0, UpdateError.Create("Nothing was saved, no change detected.")); })); public async ValueTask> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => @@ -247,8 +246,7 @@ public sealed class GovernanceService(IDbContextFactory co var portfolio = await context.Portfolios.AsNoTracking() .FirstOrDefaultAsync(p => p.Id == decodeResult.Value, cancellationToken); - return portfolio is not null - ? Result.Ok(portfolio.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(portfolio is null, NotFoundError.New) + .ToResult(portfolio!.Map()); })); } diff --git a/PostFundManagement.Application/Services/Grants/GrantsService.cs b/PostFundManagement.Application/Services/Grants/GrantsService.cs index 9c4061f..a99a0f1 100644 --- a/PostFundManagement.Application/Services/Grants/GrantsService.cs +++ b/PostFundManagement.Application/Services/Grants/GrantsService.cs @@ -38,9 +38,8 @@ public sealed class GrantsService(IDbContextFactory contex var contract = await context.Contracts.AsNoTracking() .FirstOrDefaultAsync(c => c.Id == decodeResult.Value, cancellationToken); - return contract is not null - ? Result.Ok(contract.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(contract is null, NotFoundError.New) + .ToResult(contract!.Map()); })); public async ValueTask> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -71,9 +70,8 @@ public sealed class GrantsService(IDbContextFactory contex var budget = await context.Budgets.AsNoTracking() .FirstOrDefaultAsync(b => b.Id == decodeResult.Value, cancellationToken); - return budget is not null - ? Result.Ok(budget.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(budget is null, NotFoundError.New) + .ToResult(budget!.Map()); })); public async ValueTask> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -103,9 +101,8 @@ public sealed class GrantsService(IDbContextFactory contex var award = await context.Awards.AsNoTracking().FirstOrDefaultAsync(a => a.Id == decodeResult.Value, cancellationToken); - return award is not null - ? Result.Ok(award.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(award is null, NotFoundError.New) + .ToResult(award!.Map()); })); public async ValueTask ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -121,7 +118,7 @@ public sealed class GrantsService(IDbContextFactory contex .SetProperty(u => u.CreatedBy, userId) .SetProperty(u => u.Status, ContractStatus.Active), cancellationToken); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, UpdateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, UpdateError.New); })); public async ValueTask CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -148,7 +145,7 @@ public sealed class GrantsService(IDbContextFactory contex context.Contracts.Add(contract); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -173,7 +170,7 @@ public sealed class GrantsService(IDbContextFactory contex context.Budgets.Add(budget); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -202,6 +199,6 @@ public sealed class GrantsService(IDbContextFactory contex context.Awards.Add(award); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); } diff --git a/PostFundManagement.Application/Services/Projects/ProjectService.cs b/PostFundManagement.Application/Services/Projects/ProjectService.cs index ea061c1..a53a5e4 100644 --- a/PostFundManagement.Application/Services/Projects/ProjectService.cs +++ b/PostFundManagement.Application/Services/Projects/ProjectService.cs @@ -25,7 +25,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(p => p.UpdatedBy, userId) .SetProperty(p => p.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); + return Result.OkIf(changedTotal > 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -55,9 +55,8 @@ public sealed class ProjectService(IDbContextFactory conte var project = await context.Projects.AsNoTracking() .FirstOrDefaultAsync(p => p.Id == decodeResult.Value, cancellationToken); - return project is not null - ? Result.Ok(project.Map()) - : Result.Fail(NotFoundError.Create()); + return Result.FailIf(project is null, NotFoundError.New) + .ToResult(project!.Map()); })); public async ValueTask> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) => @@ -105,7 +104,7 @@ public sealed class ProjectService(IDbContextFactory conte CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.Create("No changes detected, update cancelled.")); })); @@ -135,7 +134,7 @@ public sealed class ProjectService(IDbContextFactory conte CreatedAt = DateTime.UtcNow }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.Create("No record was created.")); })); @@ -190,9 +189,8 @@ public sealed class ProjectService(IDbContextFactory conte var milestone = await context.Milestones.AsNoTracking() .FirstOrDefaultAsync(m => m.Id == decodeResult.Value, cancellationToken); - return milestone is not null - ? Result.Ok(milestone.Map()) - : Result.Fail(NotFoundError.Create()); + return Result.FailIf(milestone is null, NotFoundError.New) + .ToResult(milestone!.Map()); })); public async ValueTask> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) => @@ -226,7 +224,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(u => u.UpdatedBy, userId) .SetProperty(u => u.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); + return Result.OkIf(changedTotal > 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -245,7 +243,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(u => u.Sector, request.Sector) .SetProperty(u => u.ProjectType, request.ProjectType), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); + return Result.OkIf(changedTotal > 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => @@ -262,9 +260,8 @@ public sealed class ProjectService(IDbContextFactory conte var activity = await context.Activities.AsNoTracking() .FirstOrDefaultAsync(a => a.Id == decodeResult.Value, cancellationToken); - return activity is not null - ? Result.Ok(activity.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(activity is null, NotFoundError.New) + .ToResult(activity!.Map()); })); public async ValueTask> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) => @@ -309,7 +306,7 @@ public sealed class ProjectService(IDbContextFactory conte Status = ApprovalStatus.Pending }); - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask UpdateProgrammeAsync(UpdateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default) => @@ -328,7 +325,7 @@ public sealed class ProjectService(IDbContextFactory conte .SetProperty(u => u.UpdatedBy, userId) .SetProperty(u => u.UpdatedAt, DateTime.UtcNow), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.Create("No changes detected, update cancelled.")); + return Result.OkIf(changedTotal > 0, UpdateError.Create("No changes detected, update cancelled.")); })); public async ValueTask> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) => @@ -343,9 +340,8 @@ public sealed class ProjectService(IDbContextFactory conte var programme = await context.Programmes.FirstOrDefaultAsync(p => p.Id == decodeResult.Value, cancellationToken); - return programme is not null - ? Result.Ok(programme.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(programme is null, NotFoundError.New) + .ToResult(programme!.Map()); })); public async ValueTask> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default) => diff --git a/PostFundManagement.Application/Services/Shared/BrowserLocalStorageService.cs b/PostFundManagement.Application/Services/Shared/BrowserLocalStorageService.cs index 8bba042..54cf872 100644 --- a/PostFundManagement.Application/Services/Shared/BrowserLocalStorageService.cs +++ b/PostFundManagement.Application/Services/Shared/BrowserLocalStorageService.cs @@ -33,9 +33,9 @@ public sealed class BrowserLocalStorageService(ProtectedLocalStorage storage) { var retrieval = await storage.GetAsync(key); - return retrieval.Success && !string.IsNullOrWhiteSpace(retrieval.Value) - ? Result.Ok(retrieval.Value) - : Result.Fail(NotFoundError.Create($"Could not find object by key {key}")); + return Result.FailIf(!retrieval.Success && string.IsNullOrWhiteSpace(retrieval.Value), + NotFoundError.Create($"Could not find object by key {key}")) + .ToResult(retrieval.Value!); })); public async ValueTask> GetAsync(string key) where TValue : class => @@ -43,8 +43,8 @@ public sealed class BrowserLocalStorageService(ProtectedLocalStorage storage) { var retrieval = await storage.GetAsync(key); - return retrieval.Success && retrieval.Value is not null - ? Result.Ok(retrieval.Value) - : Result.Fail(NotFoundError.Create($"Could not find object by key {key}")); + return Result.FailIf(!retrieval.Success && retrieval.Value is null, + NotFoundError.Create($"Could not find object by key {key}")) + .ToResult(retrieval.Value!); })); } \ No newline at end of file diff --git a/PostFundManagement.Application/Services/Shared/HashService.cs b/PostFundManagement.Application/Services/Shared/HashService.cs index 7a25365..f3d63a3 100644 --- a/PostFundManagement.Application/Services/Shared/HashService.cs +++ b/PostFundManagement.Application/Services/Shared/HashService.cs @@ -31,17 +31,18 @@ public sealed partial class HashService(IHashids hasher) : IService return Result.Ok(Convert.ToHexString(bytes).ToLowerInvariant()); } - public Result HashEncodeHex(string input) => string.IsNullOrWhiteSpace(input) || !Patterns.HexHashRegex.IsMatch(input) - ? Result.Fail(ValidationError.Create("Input must be a valid hexadecimal string.")) - : Result.Ok(hasher.EncodeHex(input)); + public Result HashEncodeHex(string input) => + Result.FailIf(string.IsNullOrWhiteSpace(input) || !Patterns.HexHashRegex.IsMatch(input), + ValidationError.Create("Input must be a valid hexadecimal string.")) + .ToResult(hasher.EncodeHex(input)); - public Result HashEncodeIntId(int id) => id < 0 - ? Result.Fail(ValidationError.Create("Id cannot be negative.")) - : Result.Ok(hasher.Encode(id)); + public Result HashEncodeIntId(int id) => + Result.FailIf(id < 0, ValidationError.Create("Id cannot be negative.")) + .ToResult(hasher.Encode(id)); - public Result HashEncodeLongId(long id) => id < 0 - ? Result.Fail(ValidationError.Create("Id cannot be negative.")) - : Result.Ok(hasher.EncodeLong(id)); + public Result HashEncodeLongId(long id) => + Result.FailIf(id < 0, ValidationError.Create("Id cannot be negative.")) + .ToResult(hasher.EncodeLong(id)); public Result DecodeIntIdHash(string hash) { @@ -50,9 +51,8 @@ public sealed partial class HashService(IHashids hasher) : IService int[] decoded = hasher.Decode(hash); - return decoded.Length == 1 - ? Result.Ok(decoded[0]) : - Result.Fail(ValidationError.Create("Invalid or modified Int hash token.")); + return Result.FailIf(decoded.Length <= 0, ValidationError.Create("Invalid or modified Int hash token.")) + .ToResult(decoded[0]); } public Result DecodeLongIdHash(string hash) @@ -62,8 +62,8 @@ public sealed partial class HashService(IHashids hasher) : IService long[] decoded = hasher.DecodeLong(hash); - return decoded.Length == 1 ? Result.Ok(decoded[0]) : - Result.Fail(ValidationError.Create("Invalid or modified Long hash token.")); + return Result.FailIf(decoded.Length <= 0, ValidationError.Create("Invalid or modified Long hash token.")) + .ToResult(decoded[0]); } public async Task> DecodeHexHash(string hex) => @@ -71,8 +71,7 @@ public sealed partial class HashService(IHashids hasher) : IService { string decoded = hasher.DecodeHex(hex); - return string.IsNullOrEmpty(decoded) - ? Result.Fail(ValidationError.Create("Invalid or corrupted hex hash.")) - : Result.Ok(decoded); + return Result.FailIf(string.IsNullOrEmpty(decoded), ValidationError.Create("Invalid or corrupted hex hash.")) + .ToResult(decoded); })); } \ No newline at end of file diff --git a/PostFundManagement.Application/Services/Shared/IdentityService.cs b/PostFundManagement.Application/Services/Shared/IdentityService.cs index 06e83a4..e2d59ac 100644 --- a/PostFundManagement.Application/Services/Shared/IdentityService.cs +++ b/PostFundManagement.Application/Services/Shared/IdentityService.cs @@ -15,6 +15,6 @@ public sealed class IdentityService(IDbContextFactory cont var userExistsAndActive = await context.Users .AnyAsync(u => u.Id == userId && u.Status == ActivityStatus.Active, cancellationToken); - return Result.FailIf(!userExistsAndActive, NotFoundError.Create()); + return Result.OkIf(userExistsAndActive, NotFoundError.Create()); })); } diff --git a/PostFundManagement.Application/Services/Shared/TokenService.cs b/PostFundManagement.Application/Services/Shared/TokenService.cs index 3eb386d..ccae082 100644 --- a/PostFundManagement.Application/Services/Shared/TokenService.cs +++ b/PostFundManagement.Application/Services/Shared/TokenService.cs @@ -29,16 +29,16 @@ public sealed class TokenService(ISecurityConnectApi connectApi, IOptions(contentRaw); - return !string.IsNullOrWhiteSpace(tokenResponse?.AccessToken) - ? Result.Ok(tokenResponse) - : Result.Fail(NotFoundError.Create("Authentication succeeded, but no access token was found in the response payload.")); + return Result.FailIf(string.IsNullOrWhiteSpace(tokenResponse?.AccessToken), + NotFoundError.Create("Authentication succeeded, but no access token was found in the response payload.")) + .ToResult(tokenResponse!); } return await Result.Try((Func>>)(async () => { var errorResult = JsonSerializer.Deserialize(contentRaw); - return Result.FailIf(errorResult != null, + return Result.OkIf(errorResult is not null, CreateError.Create($"{errorResult!.Error}: {errorResult.ErrorDescription}")); })); })); diff --git a/PostFundManagement.Application/Services/Users/UserService.cs b/PostFundManagement.Application/Services/Users/UserService.cs index 861f2ff..05efdf5 100644 --- a/PostFundManagement.Application/Services/Users/UserService.cs +++ b/PostFundManagement.Application/Services/Users/UserService.cs @@ -32,7 +32,7 @@ public sealed class UserService(IDbContextFactory contextF context.Users.Update(user); } - return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New); + return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); })); public async ValueTask> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default) => @@ -74,7 +74,7 @@ public sealed class UserService(IDbContextFactory contextF .Where(f => f.Id == userId) .ExecuteUpdateAsync(f => f.SetProperty(u => u.Status, status), cancellationToken); - return Result.FailIf(changedTotal <= 0, UpdateError.New); + return Result.OkIf(changedTotal > 0, UpdateError.New); })); public async ValueTask> GetUserAsync(Guid userId, CancellationToken cancellationToken) => @@ -85,8 +85,7 @@ public sealed class UserService(IDbContextFactory contextF var user = await context.Users.AsNoTracking() .FirstOrDefaultAsync(f => f.Id == userId, cancellationToken); - return user is not null - ? Result.Ok(user.Map()) - : Result.Fail(NotFoundError.New); + return Result.FailIf(user is null, NotFoundError.New) + .ToResult(user!.Map()); })); } -- 2.47.3