docs/en/framework/ui/angular/service-proxies.md
//[doc-seo]
{
"Description": "Learn how to efficiently create service proxies for Angular applications using ABP Framework, avoiding manual transformations and improving code clarity."
}
Calling a REST endpoint from Angular applications is common. We usually create services matching server-side controllers and interfaces matching DTOs to interact with the server. This often results in manually transforming C# code into TypeScript equivalents and that is unfortunate, if not intolerable.
To avoid manual effort, we might use a tool like NSWAG that generates service proxies. However, NSWAG has some disadvantages:
ABP introduces an endpoint that exposes server-side method contracts. When the generate-proxy command is run, ABP CLI makes an HTTP request to this endpoint and generates better-aligned client proxies in TypeScript. It organizes folders according to namespaces, adds barrel exports, and reflects method signatures in Angular services.
Before you start, please make sure you start the backend application with
dotnet run. There is a known limitation about Visual Studio, so please do not run the project using its built-in web server.
Run the following command in the root folder of the angular application:
abp generate-proxy -t ng
The generated files will be placed in a folder called proxy at the root of the target project.
Each folder will have models, enums, and services defined at related namespace accompanied by a barrel export, i.e. an index.ts file for easier imports.
The command can find application/library roots by reading the
angular.jsonfile. Make sure you have either defined your target project as thedefaultProjector pass the--targetparameter to the command. This also means that you may have a monorepo workspace.
If you've created your project with version 3.1 or later, you can skip this part since it will be already installed in your solution.
For a solution that was created before v3.1, follow the steps below to configure your Angular application:
@abp/ng.schematics package to the devDependencies of the Angular project. Run the following command in the root folder of the angular application:npm install @abp/ng.schematics -D
rootNamespace property to the /src/environments/environment.ts in your application project as shown below. MyCompanyName.MyProjectName should be replaced by the root namespace of your .NET project.export const environment: Config.Environment = {
// other environment variables...
apis: {
default: {
rootNamespace: "MyCompanyName.MyProjectName",
// other environment variables...
},
},
};
tsconfig.base.json in order to have a shortcut for importing proxies:{
// other TS configuration...
"compilerOptions": {
// other TS configuration...
"paths": {
"@proxy": ["src/app/proxy/index.ts"],
"@proxy/*": ["src/app/proxy/*"]
}
}
}
The destination the
proxyfolder is created and the paths above may change based on your project structure.
app. The object key of the modules defined in response of api/abp/api-definition. For example, if you want to generate-proxy of PermissionManagement, you should pass permissionManagement as a value.api/abp/api-definition). The property(key) name is remoteServiceName. For example for the PermissionManagement, you should pass AbpPermissionManagementpermission-management, it'll look like this (npm/ng-packs/packages/permission-management).permission-management/proxy/src/lib/proxy and the permission-management is the value of target. If you want to create a folder for the generated proxy, there are two options, you should either set the value proxy as the entryPoint or go to project.json and change the sourceRoot from packages/permission-management/src to packages/permission-management/proxy/src. No need to change the sourceRoot of project with the property. if you keep it empty, the proxy will be generated into the folder defined in the sourceRoot property.application, integration and all. The default value is application. A developer can mark a service "integration service". If you want to skip proxy generation for the service, then this is the correct setting. More info about Integration ServicesThe generate-proxy command generates one service per back-end controller and a method (property with a function value actually) for each action in the controller. These methods call backend APIs via RestService.
A variable named apiName (available as of v2.4) is defined in each service. apiName matches the module's RemoteServiceName. This variable passes to the RestService as a parameter at each request. If there is no microservice API defined in the environment, RestService uses the default. See getting a specific API endpoint from application config
The providedIn property of the services is defined as 'root'. Therefore there is no need to provide them in a module. You can use them directly by injecting as shown below:
import { BookService } from '@proxy/books';
import { inject } from '@angular/core';
@Component(/* component metadata here */)
export class BookComponent implements OnInit {
private service = inject(BookService);
ngOnInit() {
this.service.get().subscribe(
// do something with the response
);
}
}
The Angular compiler removes the services that have not been injected anywhere from the final output. See the tree-shakable providers documentation.
The generate-proxy command generates interfaces matching DTOs in the back-end. There are also a few core DTOs in the @abp/ng.core package. In combination, these models can be used to reflect the APIs.
import { PagedResultDto } from "@abp/ng.core";
import { BookDto } from "@proxy/books";
@Component(/* component metadata here */)
export class BookComponent implements OnInit {
data: PagedResultDto<BookDto> = {
items: [],
totalCount: 0,
};
}
Enums have always been difficult to populate in the frontend. The generate-proxy command generates enums in a separate file and exports a ready-to-use "options constant" from the same file. So you can import them as follows:
import { bookGenreOptions } from "@proxy/books";
@Component(/* component metadata here */)
export class BookComponent implements OnInit {
genres = bookGenreOptions;
}
...and consume the options in the template as follows:
<!-- simplified for sake of clarity -->
<select formControlName="genre">
<option [ngValue]="null">Select a genre</option>
@for (genre of genres; track genre.value) {
<option [ngValue]="genre.value">
{%{{{ genre.key }}}%}
</option>
}
</select>
Please see this article to learn more about service proxies.
For projects that utilize NX, the @abp/nx.generators package offers seamless integration. Essentially, this package serves as a wrapper specifically tailored for NX-based repositories Installation To incorporate this package into your project, run the following command:
yarn add @abp/nx.generators
To use the generator, execute the following command:
yarn nx generate @abp/nx.generators:generate-proxy
// or
yarn nx g @abp/nx.generators:generate-proxy
Note: The parameters you'd use with this generator are consistent with the standard ABP proxy generator.
When you run a project on Visual Studio using IIS Express as the web server, there will be no remote access to your endpoints. This is the default behavior of IIS Express since it explicitly protects you from the security risks of running over the network. However, that will cause the proxy generator to fail because it needs a response from the /api/abp/api-definition endpoint. You may serve your endpoints via Kestrel to avoid this. Running dotnet run in your command line (at your project folder) will do that for you.