Open Closed

ABP Proxy Generation issue #10802


User avatar
0
priyanka.dandekar created

Issue: Proxies generated for already committed entities. There is no option for selective proxy generation in ABP Suite UI. Below is the same file in repo,”employee.service.ts”, before and after creating a new entity (any entity other than employee entity). 1. GetEmployeeLookup method was removed from code after proxy generation 2. Backend API URL is modified in multiple methods Method API URL Before API URL After getEmployeeGradeLookup /api/app/employees/grade-lookup /api/app/employees/employee-grade-lookup getEmployeeLocationLookup /api/app/employees/mapped-location-lookup /api/app/employees/employee-location-lookup getEmployeeRoleLookup /api/app/employees/role-lookup' /api/app/employees/employee-role-lookup getOrganizationUnitLookup /api/app/employees/org-unit-lookup /api/app/employees/organization-unit-lookup API URL Before is consistent with backend controller code. Attached are supporting versions of same “employee.service.ts” before and after new entity creation.employeeservicebefore.txt

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

4 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • ABP Suite’s Angular proxy generation is not incremental and not selective: when you generate proxies, it regenerates the proxy files from the backend API Definition (/api/abp/api-definition). Because of that, it can rewrite already-committed proxy files (remove methods, rename method URLs, etc.) if the server-side API surface it reads differs from what your previously generated employee.service.ts was based on.

    • In ABP (including v10.4), the generated Angular URLs come from server metadata, not from the existing TypeScript file. So when you regenerate proxies, the tool will:

      1. drop methods that are no longer present (or no longer discoverable) in the API definition (e.g., GetEmployeeLookup disappears),
      2. update URL templates if the backend action’s “effective route” changed (or if the backend action name/route attributes changed), and overwrite the TS file accordingly.
    • Practical resolution (to stop proxy generation from breaking already-committed code):

      1. Do not manually edit generated proxy files under src/app/proxy/**. Treat them as generated artifacts.
      2. Wrap/adapter pattern: create your own Angular service (e.g., employee-api.service.ts) that calls the generated proxy service, and only commit/use your wrapper in business code. Then proxy regeneration won’t break your app code, only the generated layer.
      3. If you must keep stable URLs like /api/app/employees/grade-lookup etc., make sure the backend controller/action routes are explicitly fixed with attributes (e.g., [Route("api/app/employees")] on the controller + [HttpGet("grade-lookup")] on the action), and that these endpoints are visible in /api/abp/api-definition. Then regenerate proxies; the generated URLs will match those explicit routes.
    • If your backend code truly still has the old routes but the generator produces /employee-grade-lookup style paths, that indicates the backend API definition being used during generation is not the one you think (common causes: generating against a different host/port, wrong environment, wrong gateway in tiered setup). Fix by generating proxies against the correct running endpoint that exposes the real API definition for that app.

    • There is no ABP Suite UI option to generate proxies only for a single entity/service. (So the correct approach is to isolate generated files and rely on wrappers, or regenerate and commit generated output as a whole.)

    Links (verified):

    • https://docs.abp.io/en/abp/latest/UI/Angular/Service-Proxies
    • https://abp.io/contact (for non-technical / license related requests)

    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
    maliming created
    Support Team Fullstack Developer

    Hi,

    The differences in employee.service.ts come from how ABP names the navigation-property "lookup" endpoints, and that convention changed in ABP 10.3:

    • Before 10.3: the lookup is named after the related entity (Grade → GetEmployeeGradeLookup / employee-grade-lookup), and multiple relations pointing to the same entity are merged into one — that's why your self-reference GetEmployeeLookup was dropped.
    • 10.3+: the lookup is named after the foreign-key property (GradeId → GetGradeLookup / grade-lookup), and each relation, including each self-reference, keeps its own lookup.

    Your committed file has the FK-style routes (grade-lookup), but the regenerated one came out in the old entity-name style (employee-grade-lookup) with the self-reference gone. That's the pre-10.3 convention, so one of the tools you regenerate with is older than your project's ABP version (10.4).

    To pin down which one, could you share a few details:

    1. Your ABP Suite version (shown on the Suite start page), and abp --version.
    2. How the proxy gets regenerated — does it happen automatically when you create/save an entity in ABP Suite, or do you run abp generate-proxy (or an @abp/ng.schematics command) yourself?
    3. The @abp/ng.core and @abp/ng.schematics versions from your Angular package.json.
    4. If it's handy, the navigationProperties section of .suite/entities/Employee.json — that shows exactly what the generator will produce for these lookups.

    Once we see which piece is behind, the fix is to bring it up to your project's version (for example abp suite update for Suite, or aligning the @abp/ng.* packages) and regenerate. The lookup routes then come back as grade-lookup, the self-reference lookups aren't dropped, and the generated code stays consistent. One thing to expect: the method names line up with the routes too (getEmployeeGradeLookup → getGradeLookup), so you'll update those call sites in your Angular code once.

    On the "no selective generation" point — the proxy is regenerated as a whole, not per method, so regenerating always rewrites the file. Keeping the proxy folder in source control and reviewing the diff after each generation is the practical way to manage that.

    Thanks

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

    ABP Suite Version: 10.4.1 Proxy generation happen automatically when you create/save an entity in ABP Suite @abp/ng.core: 10.4.1 @abp/ng.schematics: 10.4.1 PFB navigationProperties section of .suite/entities/Employee.json

    "NavigationProperties": [ { "EntityNameWithDuplicationNumber": "Grade", "EntitySetNameWithDuplicationNumber": "EmployeeGrades", "ReferencePropertyName": "Grade", "UiPickType": "Dropdown", "IsRequired": true, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "GradeId", "DisplayProperty": "Code", "Namespace": "Pulse.EmployeeGrades", "EntityName": "EmployeeGrade", "EntitySetName": "EmployeeGrades", "DtoNamespace": "Pulse.EmployeeGrades", "DtoEntityName": "EmployeeGradeDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "Region", "EntitySetNameWithDuplicationNumber": "Regions", "ReferencePropertyName": "Region", "UiPickType": "Dropdown", "IsRequired": true, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "RegionId", "DisplayProperty": "Name", "Namespace": "Pulse.Regions", "EntityName": "Region", "EntitySetName": "Regions", "DtoNamespace": "Pulse.Regions", "DtoEntityName": "RegionDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "WorkingLocation", "EntitySetNameWithDuplicationNumber": "EmployeeLocations", "ReferencePropertyName": "WorkingLocation", "UiPickType": "Dropdown", "IsRequired": true, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "WorkingLocationId", "DisplayProperty": "Name", "Namespace": "Pulse.EmployeeLocations", "EntityName": "EmployeeLocation", "EntitySetName": "EmployeeLocations", "DtoNamespace": "Pulse.EmployeeLocations", "DtoEntityName": "EmployeeLocationDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "MappedLocation", "EntitySetNameWithDuplicationNumber": "EmployeeLocations1", "ReferencePropertyName": "MappedLocation", "UiPickType": "Dropdown", "IsRequired": true, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "MappedLocationId", "DisplayProperty": "Name", "Namespace": "Pulse.EmployeeLocations", "EntityName": "EmployeeLocation", "EntitySetName": "EmployeeLocations", "DtoNamespace": "Pulse.EmployeeLocations", "DtoEntityName": "EmployeeLocationDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "OrgUnit", "EntitySetNameWithDuplicationNumber": "OrganizationUnits", "ReferencePropertyName": "OrgUnit", "UiPickType": "Dropdown", "IsRequired": false, "IncludeEntitiesFromModules": true, "FromAbpModule": true, "Name": "OrgUnitId", "DisplayProperty": "DisplayName", "Namespace": "Volo.Abp.Identity", "EntityName": "OrganizationUnit", "EntitySetName": "OrganizationUnits", "DtoNamespace": "Volo.Abp.Identity", "DtoEntityName": "OrganizationUnitDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "Role", "EntitySetNameWithDuplicationNumber": "EmployeeRoles", "ReferencePropertyName": "Role", "UiPickType": "Dropdown", "IsRequired": true, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "RoleId", "DisplayProperty": "Name", "Namespace": "Pulse.EmployeeRoles", "EntityName": "EmployeeRole", "EntitySetName": "EmployeeRoles", "DtoNamespace": "Pulse.EmployeeRoles", "DtoEntityName": "EmployeeRoleDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "TeamLead", "EntitySetNameWithDuplicationNumber": "Employees1", "ReferencePropertyName": "TeamLead", "UiPickType": "Dropdown", "IsRequired": false, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "TeamLeadId", "DisplayProperty": "Name", "Namespace": "Pulse.Employees", "EntityName": "Employee", "EntitySetName": "Employees", "DtoNamespace": "Pulse.Employees", "DtoEntityName": "EmployeeDto", "Type": "Guid", "IsFilterable": true }, { "EntityNameWithDuplicationNumber": "ReportingManager", "EntitySetNameWithDuplicationNumber": "Employees2", "ReferencePropertyName": "ReportingManager", "UiPickType": "Dropdown", "IsRequired": false, "IncludeEntitiesFromModules": false, "FromAbpModule": false, "Name": "ReportingManagerId", "DisplayProperty": "Name", "Namespace": "Pulse.Employees", "EntityName": "Employee", "EntitySetName": "Employees", "DtoNamespace": "Pulse.Employees", "DtoEntityName": "EmployeeDto", "Type": "Guid", "IsFilterable": true }

    API routes from EmployeeController: [HttpGet] [Route("grade-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetGradeLookupAsync(LookupRequestDto input) { return _employeesAppService.GetGradeLookupAsync(input); }

    [HttpGet] [Route("region-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetRegionLookupAsync(LookupRequestDto input) { return _employeesAppService.GetRegionLookupAsync(input); }

    [HttpGet] [Route("working-location-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetWorkingLocationLookupAsync(LookupRequestDto input) { return _employeesAppService.GetWorkingLocationLookupAsync(input); }

    [HttpGet] [Route("mapped-location-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetMappedLocationLookupAsync(LookupRequestDto input) { return _employeesAppService.GetMappedLocationLookupAsync(input); }

    [HttpGet] [Route("org-unit-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetOrgUnitLookupAsync(LookupRequestDto input) { return _employeesAppService.GetOrgUnitLookupAsync(input); }

    [HttpGet] [Route("role-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetRoleLookupAsync(LookupRequestDto input) { return _employeesAppService.GetRoleLookupAsync(input); }

    [HttpGet] [Route("team-lead-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetTeamLeadLookupAsync(LookupRequestDto input) { return _employeesAppService.GetTeamLeadLookupAsync(input); }

    [HttpGet] [Route("reporting-manager-lookup")] public virtual Task<PagedResultDto<LookupDto<Guid>>> GetReportingManagerLookupAsync(LookupRequestDto input) { return _employeesAppService.GetReportingManagerLookupAsync(input); }

    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,

    Thanks for the details. Since everything is already on 10.4.1, my earlier upgrade suggestion was wrong — sorry about that. This is a bug in ABP Suite's Angular proxy generation: it names the navigation-property lookups differently from your backend controllers, so the generated URLs don't match and some lookups get dropped.

    For now, generate the proxy from the running backend instead of Suite's built-in generation:

    1. Start your HTTP API host.
    2. From the angular folder, run (replace the URL with your host's URL):
    abp generate-proxy -t ng -u https://localhost:44300 -m app
    

    This reads your actual API, so employee.service.ts matches your controllers exactly and all the lookups are there. The method names follow the backend (getGradeLookup instead of getEmployeeGradeLookup), so update those call sites once. If you regenerate the entity in Suite later, run this command again afterward.

    We'll fix this in Suite's Angular generation. Your ticket has been refunded.

    Thanks

    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 October 05, 2026, 11:32
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.