Open Closed

ABP Suite: Generating custom input class without pagination fields #10754


User avatar
0
ageiter created

What we really miss in the entities generated by the ABP Suite is a GetList-Method that returns the data without pagination. By customizing certain templates, we have now added these missing methods ourselves.

Here are some examples of our customizations:

Server.Controller.ItemController.txt:

[HttpGet]
        public virtual Task<List<%%entity-name%%Dto>> GetListAsync(Get%%entity-name-plural%%Input input)
        {
            return _%%entity-name-plural-camelcase%%AppService.GetListAsync(input);
        }

        [HttpGet]
        [Route("paged")]
        public virtual Task<PagedResultDto<%%entity-name%%Dto>> GetPagedListAsync(Get%%entity-name-plural%%Input input)
        {
            return _%%entity-name-plural-camelcase%%AppService.GetPagedListAsync(input);
        }

Server.AppService.AppService.txt:

public virtual async Task<List<%%entity-name%%Dto>> GetListAsync(Get%%entity-name-plural%%Input input)
        {
            var items = await _%%entity-name-camelcase%%Repository.GetListAsync(input.FilterText, %%input-properties%%%%<if:HasFilterableProperties>%%, %%</if:HasFilterableProperties>%%input.Sorting);

            return ObjectMapper.Map<List<%%entity-name%%>, List<%%entity-name%%Dto>>(items);
        }

        public virtual async Task<PagedResultDto<%%entity-name%%Dto>> GetPagedListAsync(Get%%entity-name-plural%%Input input)
        {
            var totalCount = await _%%entity-name-camelcase%%Repository.GetCountAsync(input.FilterText%%<if:HasFilterableProperties>%%, %%</if:HasFilterableProperties>%%%%input-properties%%);
            var items = await _%%entity-name-camelcase%%Repository.GetListAsync(input.FilterText, %%input-properties%%%%<if:HasFilterableProperties>%%, %%</if:HasFilterableProperties>%%input.Sorting, input.MaxResultCount, input.SkipCount);

            return new PagedResultDto<%%entity-name%%Dto>
            {
                TotalCount = totalCount,
                Items = ObjectMapper.Map<List<%%entity-name%%>, List<%%entity-name%%Dto>>(items)
            };
        }

Here's my problem / my question:

For my GetListAsync method, I used the same input class that’s also used for the paged list. The problem, however, is that Angular requires a value to be set for MaxResultCount, even if that value isn’t used. This is poor design and confuses developers.

How could I use the ABP Suite to generate a custom input class for this? Ideally, of course, I’d be able to create a Server.AppService.GetItemsPagedInput.txt file in addition to the Server.AppService.GetItemsInput.txt template.

Is it possible to create your own templates? If so, where would they be saved?

Thanks, Adrian

Environment:

  • Template: app
  • Template Type: Classic
  • Created ABP Studio Version: 2.2.1
  • Current ABP Studio Version: 3.0.6
  • Tiered: No
  • Multi-Tenancy: Yes
  • UI Framework: angular
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Progressive Web App: No
  • Run Progressive Web App Support: No
  • Database Provider: ef
  • Database Management System: sqlserver
  • Separate Tenant Schema: Yes
  • Mobile Framework: none
  • Public Website: No
  • Social Login: Yes
  • Include Tests: Yes
  • Kubernetes Configuration: Yes
  • Distributed Event Bus: none
  • Use Local References: No
  • Optional Modules:
    • GDPR
    • FileManagement
    • TextTemplateManagement
    • LanguageManagement
    • AuditLogging
    • OpenIddictAdmin
  • Selected Languages: German (Switzerland), English, French, German (Germany), Italian
  • Default Language: German (Switzerland)
  • Create Command: abp new Bpo -t app --ui-framework angular --database-provider ef --database-management-system sqlserver --theme leptonx --separate-tenant-schema --skip-migration --skip-migrator --without-cms-kit --dont-run-install-libs --dont-run-bundling -file-management
Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

8 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • ABP Suite doesn’t support adding brand-new template files (like an additional Server.AppService.GetItemsPagedInput.txt) that participate in generation. It generates based on the built-in template set that matches your ABP version; you can only customize/override existing templates.
    • ABP Suite doesn’t store templates in a user folder; the templates it uses are located in your solution (this is why Suite version and your ABP version must match).

    So, for your specific need (a non-paged GetListAsync input without MaxResultCount/SkipCount):

    1. Keep your extra non-paged method, but don’t reuse PagedAndSortedResultRequestDto-based input.
    2. Create a separate DTO manually (or via your own post-generation process), e.g.:
    using Volo.Abp.Application.Dtos;
    
       public class GetItemsInput : SortedResultRequestDto
       {
           public string? FilterText { get; set; }
           // your filterable properties...
       }
    

    and keep the paged one as:

    public class GetItemsPagedInput : PagedAndSortedResultRequestDto
       {
           public string? FilterText { get; set; }
           // your filterable properties...
       }
    
    1. In Angular, point the non-paged call to the non-paged input type so maxResultCount isn’t required/expected by the generated TS typings.

    Links worth noting (verified):

    • https://abp.io/support/questions/671 (explains templates are located in the solution; Suite version must match ABP version)
    • https://abp.io/support/questions/65 (template customization/outdated template behavior in Suite)
    • https://abp.io/docs/latest/studio/working-with-suite

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    ageiter created

    A somewhat clunky but probably functional workaround might be to define a second input class in GetItemsInput.txt. However, I would prefer other solutions.

    Server.AppService.GetItemsInput.txt:

    using Volo.Abp.Application.Dtos;
    using System;
    
    namespace %%solution-namespace%%%%<if:ApplicationContractsNotExists>%%%%.AppServices%%</if:ApplicationContractsNotExists>%%.%%microservice-dtos-namespace-prefix%%%%entity-namespace%%
    {
        public %%custom-code-abstract-modifier%% class Get%%entity-name-plural%%PagedInput%%custom-code-base%% : PagedAndSortedResultRequestDto
        {
            public string? FilterText { get; set; }
    
    		%%property-definitions%%
    
            public Get%%entity-name-plural%%PagedInput%%custom-code-base%%()
            {
                
            }
        }
    
        public %%custom-code-abstract-modifier%% class Get%%entity-name-plural%%Input%%custom-code-base%%
        {
            public string? FilterText { get; set; }
    
    		%%property-definitions%%
    
            public Get%%entity-name-plural%%Input%%custom-code-base%%()
            {
                
            }
        }
    }
    
    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Suite can only override the templates it already knows about. During generation it reads a fixed set of built-in template names and matches your overrides to them by file name, so a brand-new file like Server.AppService.GetItemsPagedInput.txt is never requested and just gets ignored. So adding a separate template file isn't possible, you can only override the existing ones (which you're already doing, in your solution's customized templates folder).

    You don't need a separate file for this, though. You can define the extra input class right inside your Server.AppService.GetItemsInput.txt override, and %%property-definitions%% is filled for every class in the file, so both inputs keep their filterable properties in sync automatically.

    I'd leave the default Get...Input (paged) exactly as the built-in template generates it, which keeps the default paged list and its Angular grid untouched, and just add a second non-paged class next to it:

    using Volo.Abp.Application.Dtos;
    using System;
    
    namespace %%solution-namespace%%%%<if:ApplicationContractsNotExists>%%%%.AppServices%%</if:ApplicationContractsNotExists>%%.%%microservice-dtos-namespace-prefix%%%%entity-namespace%%
    {
        public %%custom-code-abstract-modifier%% class Get%%entity-name-plural%%Input%%custom-code-base%% : PagedAndSortedResultRequestDto
        {
            public string? FilterText { get; set; }
    
            %%property-definitions%%
    
            public Get%%entity-name-plural%%Input%%custom-code-base%%()
            {
            }
        }
    
        public class Get%%entity-name-plural%%ListInput : ISortedResultRequest
        {
            public string? FilterText { get; set; }
            public string? Sorting { get; set; }
    
            %%property-definitions%%
        }
    }
    

    Then change your non-paged app service method (and the matching controller action) to take Get<Entities>ListInput, and leave the paged method on Get<Entities>Input. Since the non-paged input has no MaxResultCount/SkipCount, they won't show up in the generated Angular model anymore, so the required maxResultCount goes away.

    Two details to watch:

    • The non-paged class needs that Sorting property, since your GetListAsync passes input.Sorting to the repository. Implementing ISortedResultRequest (as above) is the cleanest way to get it without the paging fields.
    • Keep the second class plain (no %%custom-code-abstract-modifier%% / %%custom-code-base%%). Those turn the default input into an abstract ...Base class with a generated .Extended partial inheriting it, and that partial is only created for the default input name. Put them on the new class and you'd get an abstract type with nothing inheriting from it.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    ageiter created

    Thanks for the feedback. I've now successfully implemented it using a ...PagedListInput (the existing class) and ...ListInput (the new class with ISortedResultRequest). And I wanted to do it “correctly” from the start using the extended partial class, so I've also adapted that template.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    ageiter created

    A while back, I posted two feature requests under “ABP Suite feature requests”. Do you know if they were noted and, if so, whether they'll be implemented at some point?

    https://abp.io/support/questions/8803/ABP-Suite-feature-request--2025#answer-3a20f067-49ef-b56a-6a66-0d1671aa7bf2

    https://abp.io/support/questions/8803/ABP-Suite-feature-request--2025#answer-3a20f070-f3b8-a78e-2794-b2edbaa436b7

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Glad it's working now, and nice that you also wired it through the extended partial class, that's the cleaner way to keep it regeneration-safe.

    About the two requests from the Suite feature-requests thread: both are noted on our side and we do plan to implement them.

    • Not forcing a string display property on a navigation property: we'll allow picking a non-string property and leave that choice to the developer.
    • Choosing the output folder for a generated entity: we'll add support for this as well.

    I can't tie either to a specific release yet, but they're planned and not forgotten.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    ageiter created

    Perfect, thank you :-)

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    : )

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 28, 2026, 11:44
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.