Skip to content

Implemented MVP CRUDs & Secured Internal Endpoints#20

Merged
blebelo merged 6 commits into
mainfrom
apis/implementation
Jan 27, 2026
Merged

Implemented MVP CRUDs & Secured Internal Endpoints#20
blebelo merged 6 commits into
mainfrom
apis/implementation

Conversation

@blebelo
Copy link
Copy Markdown
Owner

@blebelo blebelo commented Jan 27, 2026

Summary by CodeRabbit

  • New Features
    • Course application management with approve/reject workflows; added a PowerShell tool to scaffold app-service boilerplate.
  • Security
    • Added authorization enforcement across multiple application services.
  • Chores
    • Updated NuGet/test dependencies, expanded runtime logging, and updated configuration (CORS, connection string, logging levels).
  • Refactor
    • Simplified employee DTO and reduced the public surface of the employee service interface.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Jan 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
moipone Ready Ready Preview, Comment Jan 27, 2026 3:26pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 27, 2026

Warning

Rate limit exceeded

@blebelo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 48 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Adds a PowerShell scaffolder for ABP app services; implements a CourseApplication feature (DTO, interface, CRUD app service with approve/reject and query-by-course); adjusts Employees app layer and interface (authorization attributes, removed custom methods, DTO type change); restores ShortCourse applications collection; bumps multiple package versions; expands logging and host config.

Changes

Cohort / File(s) Summary
PowerShell script
aspnet-core/Generate-AppService.ps1
New script to scaffold ABP app service interface, implementation, and DTO for a given entity and namespace.
CourseApplication feature
aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/ICourseApplicationAppService.cs, aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/CourseApplicationAppService.cs, aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/Dto/CourseApplicationDto.cs
New DTO, interface and app service. App service extends AsyncCrudAppService, adds GetApplicationsByCourseIdAsync, ApproveApplication, RejectApplication, and overrides CRUD methods with input validation and repository usage.
Employee app layer
aspnet-core/src/Moipone.PublicSite.Application/Employees/Dto/EmployeeDto.cs, aspnet-core/src/Moipone.PublicSite.Application/Employees/EmployeeAppService.cs, aspnet-core/src/Moipone.PublicSite.Application/Employees/IEmployeeAppService.cs
EmployeeDto.Address type changed to domain Address; EmployeeAppService methods annotated with [AbpAuthorize] and control flow simplified; IEmployeeAppService had many custom methods removed (now only inherits IAsyncCrudAppService).
ShortCourse updates
aspnet-core/src/Moipone.PublicSite.Application/ShortCourses/Dto/ShortCourseDto.cs, aspnet-core/src/Moipone.PublicSite.Application/ShortCourses/ShortCourseAppService.cs
Re-enabled Applications collection property on ShortCourseDto; added [AbpAuthorize] to multiple ShortCourseAppService methods.
Project dependency updates
.../Moipone.PublicSite.Application.csproj, .../Moipone.PublicSite.Core.csproj, .../EntityFrameworkCore.csproj, .../Migrator.csproj, .../Web.Core.csproj, .../Web.Host.csproj, test/...Tests.csproj
Bumped ABP/EF/other package versions (10.x), upgraded Swashbuckle/EF packages, and added System.Data.SqlClient (4.9.0) and System.Text.Encodings.Web (10.0.2) across projects.
Configuration & logging
aspnet-core/src/Moipone.PublicSite.Web.Host/appsettings.json, aspnet-core/src/Moipone.PublicSite.Web.Host/App_Data/Logs/Logs.txt
Updated Default connection string and CORS origins; lowered System/Microsoft log levels to Error; extensive new log entries added (startup, module loading, DB connection and constraint errors).
Startup minor change
aspnet-core/src/Moipone.PublicSite.Web.Host/Startup/Startup.cs
Replaced using Microsoft.OpenApi.Models; with using Microsoft.OpenApi;.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client
participant AppService as CourseApplicationAppService
participant Mapper as ObjectMapper
participant Repo as IRepository<CourseApplication, Guid>
Client->>AppService: CreateAsync(CourseApplicationDto)
AppService->>AppService: validate input
AppService->>Mapper: Map DTO -> Entity
Mapper-->>AppService: CourseApplication entity
AppService->>Repo: InsertAsync(entity)
Repo-->>AppService: persisted entity
AppService->>Mapper: Map entity -> DTO
AppService-->>Client: CourseApplicationDto (created)

Client->>AppService: ApproveApplication(Guid id, reason?)
AppService->>Repo: GetAsync(id)
Repo-->>AppService: CourseApplication entity
AppService->>AppService: update Status/DecisionDate/Reason
AppService->>Repo: UpdateAsync(entity)
Repo-->>AppService: updated entity
AppService->>Mapper: Map entity -> DTO
AppService-->>Client: CourseApplicationDto (approved)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • mblebelo

Poem

🐰 I scaffolded services with a hop and a cheer,
Course apps accept, approve, and steer,
Employees gated, permissions in line,
Packages updated, logs verbose and fine,
Hop—code is ready, carrots for all near! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objectives of the PR: implementing CRUD operations (via multiple app services for CourseApplication, Employee, ShortCourse) and securing internal endpoints (via AbpAuthorize attributes and authorization constraints).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
aspnet-core/src/Moipone.PublicSite.Web.Host/appsettings.json (1)

9-9: Move localhost CORS origins to environment-specific configuration.

Line 9 hard-codes development localhost origins in the main appsettings.json. These should be moved to appsettings.Development.json (which does not currently exist) or configured via environment variables. The main config should contain only production-appropriate origins, with environment-specific overrides for development and staging scenarios.

aspnet-core/src/Moipone.PublicSite.Application/ShortCourses/ShortCourseAppService.cs (1)

419-420: The navigation property EnrolledStudents is not loaded, causing Count to always return 0.

Since lazy loading is disabled by default in EF Core and no explicit .Include() is used in GetAsync(id), the EnrolledStudents collection will be empty. This makes course.EnrolledStudents.Count always return 0, resulting in incorrect capacity calculation. Add .Include(s => s.EnrolledStudents) to the query at line 410, or modify GetAsync in the repository to include related entities.

🤖 Fix all issues with AI agents
In
`@aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/CourseApplicationAppService.cs`:
- Around line 14-24: The CourseApplicationAppService currently exposes CRUD
operations without authorization; add authorization attributes to protect
sensitive actions by either applying [AbpAuthorize] at the class level on
CourseApplicationAppService (if all methods require protection) or by decorating
specific methods such as Create, Update, Delete, Get, and GetAll (inherited
AsyncCrudAppService overrides or newly overridden methods) with [AbpAuthorize]
(or fine-grained permission names) so only authorized callers can perform those
operations; update any overridden methods in CourseApplicationAppService to
include the attribute and ensure required permission constants or names match
your permission definitions.
- Around line 125-145: RejectApplication currently allows state changes from any
status; add the same pending-state validation used in ApproveApplication so only
applications with application.Status == RefListApplicationStatus.Pending can be
rejected. In RejectApplication, check application.Status and if it is not
RefListApplicationStatus.Pending throw a UserFriendlyException (e.g., "Only
pending applications can be rejected.") before setting Status, DecisionDate,
DecisionReason and calling _courseApplicationRepository.UpdateAsync; keep the
existing fields (DecisionDate, DecisionReason) update behavior otherwise.
- Around line 103-123: ApproveApplication currently only blocks re-approving
approved records but allows invalid transitions (e.g., approving a previously
Declined application); update CourseApplicationAppService.ApproveApplication to
validate current application.Status and throw a UserFriendlyException if Status
is Declined or any non-pending state (allow only Pending→Approved), and likewise
update CourseApplicationAppService.RejectApplication to prevent rejecting an
already Approved application (allow only Pending→Declined). Also enable nullable
reference checks for the file by adding a "#nullable enable" directive at the
top so the string? parameter on ApproveApplication is correctly recognized.

In
`@aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/Dto/CourseApplicationDto.cs`:
- Around line 1-16: CourseApplicationDto uses nullable reference types (e.g.,
string? DecisionReason) but the project lacks a consistent nullable-context
setting; align this by either enabling nullable reference types project-wide in
the .csproj (so DTOs like CourseApplicationDto and StudentDto are consistent) or
suppress CS8632 warnings globally (avoid adding file-level `#nullable`
directives); update the project-level configuration so CourseApplicationDto, its
properties (StudentId, ShortCourseId, Status, DecisionReason, DecisionDate) and
StudentDto follow the same nullable-context policy.

In `@aspnet-core/src/Moipone.PublicSite.Application/Employees/Dto/EmployeeDto.cs`:
- Around line 8-11: EmployeeDto is empty so
CreateAsync/GetAsync/GetAllAsync/UpdateAsync only handle Id; add nullable
properties matching the domain Employee to the EmployeeDto (same nullable
pattern as StudentDto) so mapping works and partial updates don't clear
fields—specifically add nullable properties: FirstName, LastName, Age, Gender,
PersonalEmail, EmployeeEmail, IdNumber, DateOfBirth, PhoneNumber, Address,
HireDate, EndDate, Position, Department, EmploymentStatus, Salary,
EmployeeNumber, EmergencyContactName, EmergencyContactPhone,
EmergencyContactRelationship, CertifiedId, ProofOfResidence, CurriculumVitae,
CertifiedHighestQualification, PoliceClearance to the EmployeeDto class
annotated with [AutoMap(typeof(Employee))] so
CreateAsync/GetAsync/GetAllAsync/UpdateAsync will receive and return the full
set of employee fields.

In
`@aspnet-core/src/Moipone.PublicSite.Application/Employees/EmployeeAppService.cs`:
- Around line 42-57: GetAllAsync lacks a null check for its
PagedAndSortedResultRequestDto input, so references to input.SkipCount and
input.MaxResultCount can NRE; add a guard at the start of GetAllAsync (in
EmployeeAppService.GetAllAsync) that throws ArgumentNullException(nameof(input))
or uses input = input ?? new PagedAndSortedResultRequestDto() as appropriate to
match project conventions, then proceed to use input.SkipCount and
input.MaxResultCount when building the query and returning the
PagedResultDto<EmployeeDto>.
- Around line 27-28: Add a specific employee permission and apply it to the
EmployeeAppService CRUD methods: define a Pages_Employees constant in
PermissionNames (e.g., PermissionNames.Pages_Employees), register that
permission in PublicSiteAuthorizationProvider so it appears in the permission
tree, and replace the generic [AbpAuthorize] on EmployeeAppService methods
(e.g., CreateAsync, UpdateAsync, DeleteAsync, GetAsync/ListAsync) with
[AbpAuthorize(PermissionNames.Pages_Employees)] so only users granted
Pages_Employees can perform employee operations.

In
`@aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Moipone.PublicSite.EntityFrameworkCore.csproj`:
- Around line 16-27: The project currently references the deprecated
System.Data.SqlClient package in the csproj; replace the PackageReference
Include="System.Data.SqlClient" Version="4.9.0" with a PackageReference to
Microsoft.Data.SqlClient (appropriate version for your target framework) so the
project uses the actively maintained driver; update any using statements or code
that reference the System.Data.SqlClient namespace to Microsoft.Data.SqlClient
and ensure the new package version is added to the csproj (same element name
PackageReference) and restore packages.

In
`@aspnet-core/src/Moipone.PublicSite.Web.Core/Moipone.PublicSite.Web.Core.csproj`:
- Around line 26-32: The ABP package versions referenced (Abp.AspNetCore,
Abp.ZeroCore, Abp.AspNetCore.SignalR) use "10.3.0", which is not a public
release; update those <PackageReference> entries to the intended, valid ABP
version (e.g., "10.0.0" or your specific pre-release like "10.1.0-rc.2") so
NuGet restore succeeds, then run dotnet restore/build to verify; ensure all
three symbols (Abp.AspNetCore, Abp.ZeroCore, Abp.AspNetCore.SignalR) use the
same, supported version.

In `@aspnet-core/src/Moipone.PublicSite.Web.Host/App_Data/Logs/Logs.txt`:
- Around line 9758-9985: The committed runtime log App_Data/Logs/Logs.txt
contains sensitive runtime info and must be removed from the repository; delete
the file from history/working tree (e.g., git rm --cached App_Data/Logs/Logs.txt
and commit), add the directory App_Data/Logs/ to .gitignore (or add the logging
sink path) to prevent future commits, and update your logging configuration
(where Serilog/NLog/ASP.NET Core logging is configured) to write logs to an
external storage or rotated files with retention/PII scrubbing instead of
committing Logs.txt.

In `@aspnet-core/src/Moipone.PublicSite.Web.Host/appsettings.json`:
- Line 3: The appsettings.json contains a hard-coded connection string under the
"Default" key (exposes live username/password); remove the literal credentials
from the "Default" entry and change the configuration to read the connection
string from a secure source (environment variable or secret store) at runtime
(e.g., via Configuration/ConnectionStrings binding or
Environment.GetEnvironmentVariable for the ConnectionStrings:Default key),
update startup/deployment to provide the secret, and immediately
rotate/invalidate the exposed DB credentials so the leaked secret is revoked.
🧹 Nitpick comments (6)
aspnet-core/Generate-AppService.ps1 (2)

33-33: Naive pluralization may produce incorrect folder/namespace names.

Appending "s" won't handle irregular plurals or words ending in 'y', 's', 'x', 'ch', 'sh' (e.g., CategoryCategorys instead of Categories, StatusStatuss instead of Statuses).

Consider using a simple pluralization helper or accepting an optional -PluralName parameter for edge cases.

♻️ Suggested improvement
 param(
     [Parameter(Mandatory = $true)]
     [string]$EntityName,

     [Parameter(Mandatory = $false)]
-    [string]$Namespace = "Moipone.PublicSite"
+    [string]$Namespace = "Moipone.PublicSite",
+
+    [Parameter(Mandatory = $false)]
+    [string]$PluralName = $null
 )

Then update the naming section:

 # ------------------ Naming ------------------
-$PluralEntityName = "$EntityName`s"
+$PluralEntityName = if ($PluralName) { $PluralName } else { "$EntityName`s" }
 $EntityLower = $EntityName.Substring(0,1).ToLower() + $EntityName.Substring(1)

87-150: Consider whether all CRUD overrides are necessary.

The generated service extends AsyncCrudAppService<> which already provides default implementations for all CRUD operations. The overrides here add null/ID validation but duplicate most of the base class logic.

Options to consider:

  1. Remove overrides and rely on base class (simpler, less boilerplate)
  2. Only override methods that need custom behavior
  3. Add authorization attributes to the generated class (e.g., [AbpAuthorize])
♻️ Minimal service relying on base class

If the goal is just scaffolding, a leaner approach:

namespace $Namespace.$PluralEntityName
{
    [AbpAuthorize] // Consider adding authorization
    public class ${EntityName}AppService
        : AsyncCrudAppService<$EntityName, ${EntityName}Dto, Guid, PagedAndSortedResultRequestDto, ${EntityName}Dto, ${EntityName}Dto>,
          I${EntityName}AppService
    {
        public ${EntityName}AppService(IRepository<$EntityName, Guid> repository)
            : base(repository)
        {
        }
        
        // Override only when custom logic is needed
    }
}
aspnet-core/src/Moipone.PublicSite.Migrator/Moipone.PublicSite.Migrator.csproj (1)

19-19: Consider using Microsoft.Data.SqlClient instead of legacy System.Data.SqlClient.

System.Data.SqlClient is generally considered legacy for modern .NET; Microsoft.Data.SqlClient is actively maintained and recommended. Switch unless you have a hard requirement for System.Data.SqlClient.

aspnet-core/src/Moipone.PublicSite.Application/ShortCourses/Dto/ShortCourseDto.cs (1)

26-27: Initialize collection properties to avoid null references.

Both EnrolledStudents and Applications are non-nullable collections without initializers. Consumers may encounter NullReferenceException when iterating over these properties if not explicitly set.

♻️ Proposed fix
-        public ICollection<StudentDto> EnrolledStudents { get; set; }
-        public ICollection<CourseApplicationDto> Applications { get; set; }
+        public ICollection<StudentDto> EnrolledStudents { get; set; } = new List<StudentDto>();
+        public ICollection<CourseApplicationDto> Applications { get; set; } = new List<CourseApplicationDto>();
aspnet-core/src/Moipone.PublicSite.Application/ShortCourses/ShortCourseAppService.cs (1)

330-370: ReopenApplicationsAsync duplicates OpenApplicationsAsync logic.

Both methods set IsActive = true with identical implementation. Consider consolidating or having ReopenApplicationsAsync delegate to OpenApplicationsAsync.

♻️ Proposed simplification
 [AbpAuthorize]
 public async Task<ShortCourseDto> ReopenApplicationsAsync(Guid id)
 {
-    try
-    {
-        if (id == Guid.Empty)
-        {
-            throw new UserFriendlyException(
-                "Invalid short course ID.",
-                Abp.Logging.LogSeverity.Warn
-            );
-        }
-
-        var shortCourse = await _shortCourseRepository.GetAsync(id);
-
-        if (shortCourse == null)
-        {
-            throw new UserFriendlyException(
-                $"Short course with ID {id} not found.",
-                Abp.Logging.LogSeverity.Warn
-            );
-        }
-
-        shortCourse.IsActive = true;
-        var updatedShortCourse = await _shortCourseRepository.UpdateAsync(shortCourse);
-
-        return ObjectMapper.Map<ShortCourseDto>(updatedShortCourse);
-    }
-    catch (UserFriendlyException)
-    {
-        throw;
-    }
-    catch (Exception ex)
-    {
-        Logger.Error($"Error reopening applications for short course with ID {id}", ex);
-        throw new UserFriendlyException(
-            $"Could not reopen applications. Error: {ex.Message}",
-            Abp.Logging.LogSeverity.Error
-        );
-    }
+    // Reopen is semantically equivalent to Open
+    return await OpenApplicationsAsync(id);
 }
aspnet-core/src/Moipone.PublicSite.Core/Moipone.PublicSite.Core.csproj (1)

21-21: Consider using Microsoft.Data.SqlClient instead of System.Data.SqlClient.

System.Data.SqlClient is in deprecation and maintenance mode. Microsoft recommends Microsoft.Data.SqlClient for all modern .NET projects (including .NET 10), as it receives active development, newer SQL Server features, and continuous security updates.

Comment thread aspnet-core/src/Moipone.PublicSite.Web.Host/App_Data/Logs/Logs.txt
Comment thread aspnet-core/src/Moipone.PublicSite.Web.Host/appsettings.json
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@aspnet-core/src/Moipone.PublicSite.Web.Host/Startup/Startup.cs`:
- Line 13: The file imports the wrong OpenAPI namespace; update the using to
reference Microsoft.OpenApi.Models so types used in ConfigureSwagger
(OpenApiInfo, OpenApiContact, OpenApiLicense, OpenApiSecurityScheme,
ParameterLocation, SecuritySchemeType) resolve correctly; locate the
ConfigureSwagger method and replace the incorrect Microsoft.OpenApi import with
Microsoft.OpenApi.Models to fix the compilation errors.

Comment thread aspnet-core/src/Moipone.PublicSite.Web.Host/Startup/Startup.cs
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/CourseApplicationAppService.cs`:
- Around line 68-80: UpdateAsync currently maps all fields from
CourseApplicationDto into the entity allowing uncontrolled changes to workflow
fields; modify CourseApplicationAppService.UpdateAsync so that
workflow-controlled fields (Status, DecisionDate, DecisionReason) are not
overwritten by the incoming DTO — either remove those properties from the
ObjectMapper.Map call (map only allowed fields or use a manual assign for safe
fields) or explicitly set entity.Status/DecisionDate/DecisionReason back to
their original values before calling _courseApplicationRepository.UpdateAsync;
alternatively, protect the method with an authorization attribute (e.g., add
[AbpAuthorize] to UpdateAsync) if the intent is to restrict updates to
authorized users.
🧹 Nitpick comments (3)
aspnet-core/src/Moipone.PublicSite.Application/CourseApplications/CourseApplicationAppService.cs (3)

19-25: Redundant repository field.

The _courseApplicationRepository field duplicates the Repository property inherited from AsyncCrudAppService. You can use Repository directly throughout the service.

♻️ Proposed simplification
     public class CourseApplicationAppService
         : AsyncCrudAppService<CourseApplication, CourseApplicationDto, Guid, PagedAndSortedResultRequestDto, CourseApplicationDto, CourseApplicationDto>,
           ICourseApplicationAppService
     {
-        private readonly IRepository<CourseApplication, Guid> _courseApplicationRepository;
-
         public CourseApplicationAppService(IRepository<CourseApplication, Guid> courseApplicationRepository)
             : base(courseApplicationRepository)
         {
-            _courseApplicationRepository = courseApplicationRepository;
         }

Then replace _courseApplicationRepository with Repository in the methods.


27-38: Consider validating required fields.

The method validates that input is not null, but doesn't validate that StudentId and ShortCourseId are non-empty GUIDs. Invalid GUIDs could result in orphaned or invalid application records.

Based on learnings, keeping this method public (no auth) is intentional.

🛡️ Proposed validation
 public override async Task<CourseApplicationDto> CreateAsync(CourseApplicationDto input)
 {
     if (input == null)
     {
         throw new UserFriendlyException("CourseApplication data cannot be null.");
     }

+    if (input.StudentId == Guid.Empty)
+    {
+        throw new UserFriendlyException("Student ID is required.");
+    }
+
+    if (input.ShortCourseId == Guid.Empty)
+    {
+        throw new UserFriendlyException("Course ID is required.");
+    }
+
     var entity = ObjectMapper.Map<CourseApplication>(input);
     var result = await _courseApplicationRepository.InsertAsync(entity);

     return ObjectMapper.Map<CourseApplicationDto>(result);
 }

40-55: Sorting parameter is ignored.

The PagedAndSortedResultRequestDto input includes a Sorting property, but the implementation always sorts by Id. Consider honoring the sorting parameter or using PagedResultRequestDto instead if sorting isn't needed.

♻️ Option 1: Honor sorting with dynamic ordering

You can use ABP's IQueryable extensions or a library like System.Linq.Dynamic.Core to apply dynamic sorting:

 public override async Task<PagedResultDto<CourseApplicationDto>> GetAllAsync(PagedAndSortedResultRequestDto input)
 {
     var query = Repository.GetAll();
     var totalCount = await AsyncQueryableExecuter.CountAsync(query);

+    if (!string.IsNullOrWhiteSpace(input.Sorting))
+    {
+        query = query.OrderBy(input.Sorting);
+    }
+    else
+    {
+        query = query.OrderBy(x => x.Id);
+    }
+
     var items = await AsyncQueryableExecuter.ToListAsync(
-        query.OrderBy(x => x.Id)
-             .Skip(input.SkipCount)
+        query.Skip(input.SkipCount)
              .Take(input.MaxResultCount)
     );

@blebelo blebelo temporarily deployed to apis/implementation - Moipone PS API PR #20 January 27, 2026 15:25 — with Render Destroyed
@blebelo
Copy link
Copy Markdown
Owner Author

blebelo commented Jan 27, 2026

@coderabbitai resolve

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 27, 2026

✅ Actions performed

Comments resolved.

Copy link
Copy Markdown
Collaborator

@mblebelo mblebelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All checks passed and conversations resolved ✅

@blebelo blebelo merged commit 79ff986 into main Jan 27, 2026
9 of 10 checks passed
@blebelo blebelo deleted the apis/implementation branch January 28, 2026 20:13
@coderabbitai coderabbitai Bot mentioned this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants