Starts in:
3 DAYS
14 HRS
42 MIN
51 SEC
Starts in:
3 D
14 H
42 M
51 S

Introducing the Angular Service Proxy Generation

User Avatar
4 years ago, 10808 views, 3 comments
Cover Image

Introducing the Angular Service Proxy Generation

ABP Angular Service Proxy System generates TypeScript services and models to consume your backend HTTP APIs developed using the ABP Framework. So, you don't manually create models for your server side DTOs and perform raw HTTP calls to the server.

ABP Framework has introduced the new Angular Service Proxy Generation system with the version 3.1. While this feature was available since the v2.3, it was not well covering some scenarios, like inheritance and generic types and had some known problems. With the v3.1, we've re-written it using the Angular Schematics system. Now, it is much more stable and feature rich.

This post introduces the service proxy generation system and highlights some important features.

Installation

ABP CLI

You need to have the ABP CLI to use the system. So, install it if you haven't installed before:

dotnet tool install -g Volo.Abp.Cli

If you already have installed it before, you can update to the latest version:

dotnet tool update -g Volo.Abp.Cli

Project Configuration

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 the angular application:

  • Add @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 --save-dev
  • Add rootNamespace entry into the apis/default section in the /src/environments/environment.ts, as shown below:
apis: {
  default: {
    ...
    rootNamespace: 'Acme.BookStore'
  },    
}

Acme.BookStore should be replaced by the root namespace of your .NET project. This ensures to not create unnecessary nested folders while creating the service proxy code. This value is AngularProxyDemo for the example solution explained below.

  • Finally, add the following paths to the tsconfig.base.json to have a shortcut while importing proxies:
"paths": {
    "@proxy": ["src/app/proxy/index.ts"],
    "@proxy/*": ["src/app/proxy/*"]
}

Basic Usage

Project Creation

If you already have a solution, you can skip this section.

You need to create your solution with the Angular UI. You can use the ABP CLI to create a new solution:

abp new AngularProxyDemo -u angular

Run the Application

The backend application must be up and running to be able to use the service proxy code generation system.

See the getting started guide if you don't know details of creating and running the solution.

Backend

Assume that we have an IBookAppService interface:

using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;

namespace AngularProxyDemo.Books
{
    public interface IBookAppService : IApplicationService
    {
        public Task<List<BookDto>> GetListAsync();
    }
}

That uses a BookDto defined as shown:

using System;
using Volo.Abp.Application.Dtos;

namespace AngularProxyDemo.Books
{
    public class BookDto : EntityDto<Guid>
    {
        public string Name { get; set; }

        public DateTime PublishDate { get; set; }
    }
}

And implemented as the following:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;

namespace AngularProxyDemo.Books
{
    public class BookAppService : ApplicationService, IBookAppService
    {
        public async Task<List<BookDto>> GetListAsync()
        {
            //TODO: get books from a database...
        }
    }
}

It simply returns a list of books. You probably want to get the books from a database, but it doesn't matter for this article.

HTTP API

Thanks to the auto API controllers system of the ABP Framework, we don't have to develop API controllers manually. Just run the backend (HttpApi.Host) application that shows the Swagger UI by default. You will see the GET API for the books:

swagger

Service Proxy Generation

Open a command line in the root folder of the Angular application and execute the following command:

abp generate-proxy

It should produce an output like the following:

...
CREATE src/app/proxy/books/book.service.ts (446 bytes)
CREATE src/app/proxy/books/models.ts (148 bytes)
CREATE src/app/proxy/books/index.ts (57 bytes)
CREATE src/app/proxy/index.ts (33 bytes)

generate-proxy command can take some some optional parameters for advanced scenarios (like modular development). You can take a look at the documentation.

The Generated Code

src/app/proxy/books/book.service.ts: This is the service that can be injected and used to get the list of books;

import type { BookDto } from './models';
import { RestService } from '@abp/ng.core';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class BookService {
  apiName = 'Default';

  getList = () =>
    this.restService.request<any, BookDto[]>({
      method: 'GET',
      url: `/api/app/book`,
    },
    { apiName: this.apiName });

  constructor(private restService: RestService) {}
}

src/app/proxy/books/models.ts: This file contains the modal classes corresponding to the DTOs defined in the server side;

import type { EntityDto } from '@abp/ng.core';

export interface BookDto extends EntityDto<string> {
  name: string;
  publishDate: string;
}

There are a few more files have been generated to help you import the types easier.

How to Import

You can now import the BookService into any Angular component and use the getList() method to get the list of books.

import { BookService, BookDto } from '../proxy/books';

You can also use the @proxy as a shortcut of the proxy folder:

import { BookService, BookDto } from '@proxy/books';

About the Generated Code

The generated code is;

  • Simple: It is almost identical to the code if you've written it yourself.
  • Splitted: Instead of a single, large file;
    • It creates a separate .ts file for every backend service. Model (DTO) classes are also grouped per service.
    • It understands the modularity, so creates the services for your own module (or the module you've specified).
  • Object oriented;
    • Supports inheritance of server side DTOs and generates the code respecting to the inheritance structure.
    • Supports generic types.
    • Supports re-using type definitions across services and doesn't generate the same DTO multiple times.
  • Well-aligned to the backend;
    • Service method signatures match exactly with the services on the backend services. This is achieved by a special endpoint exposed by the ABP Framework that well defines the backend contracts.
    • Namespaces are exactly matches to the backend services and DTOs.
  • Well-aligned with the ABP Framework;
    • Recognizes the standard ABP Framework DTO types (like EntityDto, ListResultDto... etc) and doesn't repeat these classes in the application code, but uses from the @abp/ng.core package.
    • Uses the RestService defined by the @abp/ng.core package which simplifies the generated code, keeps it short and re-uses all the logics implemented by the RestService (including error handling, authorization token injection, using multiple server endpoints... etc).

These are the main motivations behind the decision of creating a service proxy generation system, instead of using a pre-built tool like NSWAG.

Other Examples

Let me show you a few more examples.

Updating an Entity

Assume that you added a new method to the server side application service, to update a book:

public Task<BookDto> UpdateAsync(Guid id, BookUpdateDto input);

BookUpdateDto is a simple class defined shown below:

using System;

namespace AngularProxyDemo.Books
{
    public class BookUpdateDto
    {
        public string Name { get; set; }

        public DateTime PublishDate { get; set; }
    }
}

Let's re-run the generate-proxy command:

abp generate-proxy

This command will re-generate the proxies by updating some files. Let's see some of the changes;

book.service.ts

import type { BookDto, BookUpdateDto } from './models';
import { RestService } from '@abp/ng.core';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class BookService {
  apiName = 'Default';

  getList = () =>
    this.restService.request<any, BookDto[]>({
      method: 'GET',
      url: `/api/app/book`,
    },
    { apiName: this.apiName });

  update = (id: string, input: BookUpdateDto) =>
    this.restService.request<any, BookDto>({
      method: 'PUT',
      url: `/api/app/book/${id}`,
      body: input,
    },
    { apiName: this.apiName });

  constructor(private restService: RestService) {}
}

update function has been added to the BookService that gets an id and a BookUpdateDto as the parameters.

models.ts

import type { EntityDto } from '@abp/ng.core';

export interface BookDto extends EntityDto<string> {
  name: string;
  publishDate: string;
}

export interface BookUpdateDto {
  name: string;
  publishDate: string;
}

Added a new DTO class: BookUpdateDto.

Advanced Example

In this example, I want to show a DTO structure using inheritance, generics, arrays and dictionaries.

I've created an IOrderAppService as shown below:

using System.Threading.Tasks;
using Volo.Abp.Application.Services;

namespace AngularProxyDemo.Orders
{
    public interface IOrderAppService : IApplicationService
    {
        public Task CreateAsync(OrderCreateDto input);
    }
}

OrderCreateDto and the related DTOs are as the followings;

using System;
using System.Collections.Generic;
using Volo.Abp.Data;

namespace AngularProxyDemo.Orders
{
    public class OrderCreateDto : IHasExtraProperties
    {
        public Guid CustomerId { get; set; }

        public DateTime CreationTime { get; set; }

        //ARRAY of DTOs
        public OrderDetailDto[] Details { get; set; }

        //DICTIONARY
        public Dictionary<string, object> ExtraProperties { get; set; }
    }
    
    public class OrderDetailDto : GenericDetailDto<int> //INHERIT from GENERIC
    {
        public string Note { get; set; }
    }
    
    //GENERIC class
    public abstract class GenericDetailDto<TCount>
    {
        public Guid ProductId { get; set; }

        public TCount Count { get; set; }
    }
}

When I run the abp generate-proxy command again, I see there are some created and updated files. Let's see some important ones;

src/app/proxy/orders/order.service.ts

import type { OrderCreateDto } from './models';
import { RestService } from '@abp/ng.core';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class OrderService {
  apiName = 'Default';

  create = (input: OrderCreateDto) =>
    this.restService.request<any, void>({
      method: 'POST',
      url: `/api/app/order`,
      body: input,
    },
    { apiName: this.apiName });

  constructor(private restService: RestService) {}
}

src/app/proxy/orders/models.ts

export interface GenericDetailDto<TCount> {
  productId: string;
  count: TCount;
}

export interface OrderCreateDto {
  customerId: string;
  creationTime: string;
  details: OrderDetailDto[];
  extraProperties: Record<string, object>;
}

export interface OrderDetailDto extends GenericDetailDto<number> {
  note: string;
}

Conclusion

abp generate-proxy is a very handy command that creates all the necessary code to consume your ABP based backend HTTP APIs. It generates a clean code that is well aligned to the backend services and benefits from the power of TypeScript (by using generics, inheritance...).

The Documentation

See the documentation for details of the Angular Service Proxy Generation.

3 comments

Leave Comment
User Avatar
kishore.sahasranaman@gmail.com 4 years ago

Would it be possible to access the "Required Properties" (required: list) from Proxies generated? https://swagger.io/docs/specification/data-models/data-types/#required

User Avatar
joe@tronactive.com 4 years ago

Would this be used for commercial version as well?

User Avatar
hikalkan 4 years ago

Everyting in the ABP Framework is usable in the ABP Commercial. So, the answer is YES! BTW, ABP Commercial has ABP Suite which can create a full stack page for an entity. It uses the same proxy generation system when you create a new entity with the Angular UI.

More From Hikalkan

Announcing ABP Studio (beta) General Availability

ABP Studio (beta) is generally available to everyone and ready for download. Continue Reading

hikalkan July 2024

Unifying the ABP Platform

Some big changes and improvements are coming to the ABP.IO Platform soon Continue Reading

hikalkan April 2024

ABP.IO Platform 7.1 Final Has Been Released

Introducing the ABP.IO Platform version 7.1! Continue Reading

hikalkan March 2023

ABP.IO Platform 5.2 Final Has Been Released

Introducing the ABP.IO Platform version 5.2.0! Continue Reading

hikalkan April 2022

ABP.IO Platform 5.2 RC Has Been Published

Introducing the new features and changes coming with ABP Framework and ABP Commercial version 5.2. Continue Reading

hikalkan March 2022

ABP.IO Platform v5.1 Has Been Released

Introducing the new features and changes coming with ABP Framework and ABP Commercial version 5.1. Continue Reading

hikalkan January 2022

ABP.IO Platform 5.0 RC.1 Has Been Released

Introducing the ABP v5.0 RC and the new features coming with this version. Continue Reading

hikalkan November 2021

ABP.IO Platform 4.4 Final Has Been Released!

ABP Framework and ABP Commercial 4.4 versions have been released. Continue Reading

hikalkan August 2021

ABP Platform 4.4 RC Has Been Released

This post covers the new features and changes coming with the ABP.IO platform version 4.4. Continue Reading

hikalkan June 2021

ABP.IO Platform v4.3 Has Been Released!

Introducing the ABP.IO Platform version 4.3.0! Continue Reading

hikalkan April 2021

ABP Commercial 4.3 RC Has Been Published

Introducing the ABP Commercial v4.3 RC and the new features coming with this version Continue Reading

hikalkan April 2021

ABP Framework 4.3 RC Has Been Published

Introducing the ABP v4.3 RC and the new features coming with this version Continue Reading

hikalkan April 2021

ABP.IO Platform 4.2 Final Has Been Released!

ABP Framework and ABP Commercial 4.2 versions have been released today. Continue Reading

hikalkan January 2021

ABP.IO Platform v4.2 RC Has Been Released!

This post covers the new features and changes coming with the ABP.IO platform 4.2 version. Continue Reading

hikalkan January 2021

ABP.IO Platform v4.1 Final Has Been Released!

ABP Framework and ABP Commercial 4.1 versions have been released. Continue Reading

hikalkan January 2021

ABP.IO Platform v4.1 RC Has Been Released!

Released ABP.IO Platform v4.1 RC. Some new features: Module Entity Extensions, Blazor UI Improvements, Spanish Language Translation etc. Learn more... Continue Reading

hikalkan December 2020

ABP.IO Platform 4.0 with .NET 5.0 in the 4th Year!

Released ABP.IO Platform v4.0 Final. Some new features: Migrated to .NET 5.0, Stable Blazor UI, Identity Server 4 Upgrade, Moved to System.Text.Jso... Continue Reading

hikalkan December 2020

ABP.IO Platform v4.0 RC Has Been Released based on .NET 5.0!

Released ABP.IO Platform v4.0 RC. Some new features: Migrated to .NET 5.0, Stable Blazor UI, Identity Server 4 Upgrade, Moved to System.Text.Json, ... Continue Reading

hikalkan November 2020

ABP Framework & ABP Commercial 3.3 Final Have Been Released

Released ABP v3.3. Some new features: New modules & features for the Blazor UI, Automatic Validation for AntiForgery Token for HTTP APIs, Rebus Int... Continue Reading

hikalkan October 2020

ABP Framework & ABP Commercial v3.3 RC Have Been Released

Released ABP v3.3 RC. Some new features: New modules & features for the Blazor UI, Automatic Validation for AntiForgery Token for HTTP APIs, Rebus ... Continue Reading

hikalkan October 2020

ABP Framework v3.2 Final Has Been Released

Released ABP v3.2 final. Some new features: The Blazor UI, MongoDB ACID Transactions, Kafka Integration for the Distributed Event Bus etc. Learn mo... Continue Reading

hikalkan October 2020

ABP Framework & ABP Commercial 3.2 RC With The New Blazor UI 🚀

Released ABP v3.2 RC. Some new features: The Blazor UI, MongoDB ACID Transactions, Kafka Integration for the Distributed Event Bus etc. Learn more ... Continue Reading

hikalkan September 2020

ABP Framework v3.1 Final Has Been Released

Released ABP v3.1 final. Some new features: Angular Service Proxies, Authorization Code Flow for the Angular UI, Global Feature System etc. Learn m... Continue Reading

hikalkan September 2020

ABP Framework v3.1 RC Has Been Released

Released ABP v3.1 RC. Some new features: Angular Service Proxies, Authorization Code Flow for the Angular UI, Global Feature System etc. Learn more... Continue Reading

hikalkan August 2020

ABP Framework v3.0 Has Been Released

Released ABP v3.0. Some new features: Angular 10, The Oracle Integration Package, Azure BLOB Storage Provider etc. Learn more about what's new with... Continue Reading

hikalkan July 2020

ABP Framework v2.9.0 Has Been Released

Released ABP v2.9.0. Some new features: Organization Units System, Blob Storing Package, EF Core Oracle Integration Package, Chat Module Angular UI... Continue Reading

hikalkan June 2020

ABP v2.8.0 Releases & Road Map

Released ABP Framework and ABP Commercial v2.8. Some new features: SignalR Integration Package, RTL Support for the MVC UI, New Lepton Theme Styles... Continue Reading

hikalkan May 2020

ABP Framework v2.7.0 Has Been Released!

Released ABP Framework v2.7. Some new features: Object Extending System, Text Templating Package, Subscribing to the Exceptions etc. Learn more abo... Continue Reading

hikalkan May 2020

ABP Framework v2.3.0 Has Been Released!

Released ABP Framework v2.3. Some new features: React Native Mobile App, Angular TypeScript Proxy Generator, CRUD app service etc. See the GitHub m... Continue Reading

hikalkan March 2020

ABP Framework v2.0 and the ABP Commercial

Released ABP Framework v2.0 and ABP Commercial. See the release notes for changes. Create a demo to see application startup template of ABP Commerc... Continue Reading

hikalkan January 2020

ABP v1.0 Has Been Finally Released

Released the first stable ABP v1.0, after ~3 years of continuous development! Start playing with the new ABP framework now. See the GitHub mileston... Continue Reading

hikalkan October 2019

ABP v0.21 Has Been Released based on the ASP.NET Core 3.0

Released ABP v0.21 with no new feature. The release is just upgrade to the stable AspNet Core 3.0. Check v0.20 release notes for new features, and ... Continue Reading

hikalkan September 2019

ABP v0.19 Release With New Angular UI

Released ABP v0.19 with 90+ issues resolved and 650+ commits pushed. Some new features: Angular UI, Widget System. See the roadmap for all upcomings. Continue Reading

hikalkan August 2019

ABP CLI, New Templates & Features v0.18 Release

Released ABP v0.18 with 80+ issues resolved and 550+ commits pushed. Changes: ABP CLI command line tool, and new startup templates. See the roadmap... Continue Reading

hikalkan June 2019

Microservice Demo, Projects Status and Road Map

See microservice solution demo documentation for a detailed explanation of the solution. It aims to demonstrate a simple yet complete microservice ... Continue Reading

hikalkan February 2019