abp icon indicating copy to clipboard operation
abp copied to clipboard

Angular - cli proxy generation error on GET request with nested Dto

Open nev-21 opened this issue 4 years ago • 6 comments

Abp version

4.4.0 UI: Angular DB: MSSQL

Reproduce

I have a module with an AppService which is not related to abp entities or abp dtos (like EntityDto). This service is just used to expose endpoints that call a custom class (ITransientDependency) that I use as a repository (injecting Dbcontext) to run raw sql.

AppService

    [Authorize]
    public class CustomAppService : ApplicationService
    {
        // .... inject repo
        
        public async Task<IEnumerable<OutPutDto>> GetRecordsAsync(InputDto filter)
        {
            var dtos = await _repo.GetRecords(filter);
            return dtos;
        }
    }

Repository

    public class CustomRepository : ICustomRepository, ITransientDependency
    {
        // .... inject DbContext

        public async Task<List<OutputDto>> GetRecords(InputDto filter)
        {
            var result = // .... raw sql (linq), using filter data
            return await result.ToListAsync();
        }
    }

InputDto (Nested)

    public class InputDto
    {
        public OperationDto FirstOperation{ get; set; }
        public OperationDto SecondOperation { get; set; }
    }

    public class OperationDto
    {
        public string Operator { get; set; }
        public List<string> Values { get; set; }
    }

The issue

When I run:

abp generate-proxy -m module-name

in angular root folder, i generate the proxies folder and everything ok except for this detail:

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

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

  getRecord = (filter: InputDto) =>
    this.restService.request<any, outputDto>({
      method: 'GET',
      url: '/api/module-name/custom/record',
      params: {
            // ERROR HERE, Property 'firstOperation_Operator' does not exist on type 'InputDto'
            firstOperation_Operator: filter.firstOperation_Operator,
            firstOperation_Values: filter.firstOperation_Values, // ERROR HERE
            secondOperation_Operator: filter.secondOperation_Operator, // ERROR HERE
            secondOperation_Values: filter.secondOperation_Values // ERROR HERE
        },
    },
    { apiName: this.apiName });

    constructor(private restService: RestService) {}
}

I think It should be:

firstOperation_Operator: filter.firstOperation.operator,

Please Help!

nev-21 avatar Aug 24 '21 15:08 nev-21

Hi @nev-21

Can the share the generate-proxy.json so that we can find the source of the problem.

mehmet-erim avatar Aug 25 '21 08:08 mehmet-erim

Hi @mehmet-erim, yes of course, I deleted the parts that are not necessary.

{
  "generated": [
    "app",
    "module"
  ],
  "modules": {
    "module": {
      "rootPath": "module",
      "remoteServiceName": "Default",
      "controllers": {
        "Company.Module.CustomReport.CustomAppService": {
          "controllerName": "Custom",
          "type": "Company.Module.CustomReport.CustomAppService",
          "interfaces": [
            {
              "type": "Volo.Abp.Validation.IValidationEnabled"
            },
            {
              "type": "Volo.Abp.Auditing.IAuditingEnabled"
            },
            {
              "type": "Volo.Abp.GlobalFeatures.IGlobalFeatureCheckingEnabled"
            }
          ],
          "actions": {
            "GetRecordsAsyncByFilter": {
              "uniqueName": "GetRecordsAsyncByFilter",
              "name": "GetRecordsAsync",
              "httpMethod": "GET",
              "url": "api/module/custom/records",
              "supportedVersions": [],
              "parametersOnMethod": [
                {
                  "name": "filter",
                  "typeAsString": "Company.Module.CustomReport.InputDto, Company.Module.Domain",
                  "type": "Company.Module.CustomReport.InputDto",
                  "typeSimple": "Company.Module.CustomReport.InputDto",
                  "isOptional": false,
                  "defaultValue": null
                }
              ],
              "parameters": [
                {
                  "nameOnMethod": "filter",
                  "name": "FirstOperation.Operator",
                  "jsonName": null,
                  "type": "System.String",
                  "typeSimple": "string",
                  "isOptional": false,
                  "defaultValue": null,
                  "constraintTypes": null,
                  "bindingSourceId": "ModelBinding",
                  "descriptorName": "filter"
                },
                {
                  "nameOnMethod": "filter",
                  "name": "FirstOperation.Values",
                  "jsonName": null,
                  "type": "System.Collections.Generic.List<System.String>",
                  "typeSimple": "[string]",
                  "isOptional": false,
                  "defaultValue": null,
                  "constraintTypes": null,
                  "bindingSourceId": "ModelBinding",
                  "descriptorName": "filter"
                },
                {
                  "nameOnMethod": "filter",
                  "name": "SecondOperation.Operator",
                  "jsonName": null,
                  "type": "System.String",
                  "typeSimple": "string",
                  "isOptional": false,
                  "defaultValue": null,
                  "constraintTypes": null,
                  "bindingSourceId": "ModelBinding",
                  "descriptorName": "filter"
                },
                {
                  "nameOnMethod": "filter",
                  "name": "SecondOperation.Values",
                  "jsonName": null,
                  "type": "System.Collections.Generic.List<System.String>",
                  "typeSimple": "[string]",
                  "isOptional": false,
                  "defaultValue": null,
                  "constraintTypes": null,
                  "bindingSourceId": "ModelBinding",
                  "descriptorName": "filter"
                }
              ],
              "returnValue": {
                "type": "System.Collections.Generic.IEnumerable<Company.Module.CustomReport.OutputDto>",
                "typeSimple": "[Company.Module.CustomReport.OutputDto]"
              },
              "allowAnonymous": false
            }
          }
        }
      }
    }
  },
  "types": {
    "Company.Module.CustomReport.InputDto": {
      "baseType": null,
      "isEnum": false,
      "enumNames": null,
      "enumValues": null,
      "genericArguments": null,
      "properties": [
        {
          "name": "FirstOperation",
          "jsonName": null,
          "type": "Company.Module.CustomReport.OperationDto",
          "typeSimple": "Company.Module.CustomReport.OperationDto",
          "isRequired": false
        },
        {
          "name": "SecondOperation",
          "jsonName": null,
          "type": "Company.Module.CustomReport.OperationDto",
          "typeSimple": "Company.Module.CustomReport.OperationDto",
          "isRequired": false
        }
      ]
    },
    "Company.Module.CustomReport.OperationDto": {
      "baseType": null,
      "isEnum": false,
      "enumNames": null,
      "enumValues": null,
      "genericArguments": null,
      "properties": [
        {
          "name": "Operator",
          "jsonName": null,
          "type": "System.String",
          "typeSimple": "string",
          "isRequired": false
        },
        {
          "name": "Values",
          "jsonName": null,
          "type": "[System.String]",
          "typeSimple": "[string]",
          "isRequired": false
        }
      ]
    },
    "Company.Module.CustomReport.OutputDto": {
      "baseType": null,
      "isEnum": false,
      "enumNames": null,
      "enumValues": null,
      "genericArguments": null,
      "properties": [
        {
          "name": "Nombre",
          "jsonName": null,
          "type": "System.String",
          "typeSimple": "string",
          "isRequired": false
        }
      ]
    }
  }
}

nev-21 avatar Aug 26 '21 01:08 nev-21

Hi @nev-21,

Can you replace the getRecord method with the following:

  getRecord = (filter: InputDto) =>
    this.restService.request<any, outputDto>({
      method: 'GET',
      url: '/api/module-name/custom/record',
      params: {
            ['FirstOperation.Operator']: filter.firstOperation.operator,
            ['FirstOperation.Values']: filter.firstOperation.values,
            ['SecondOperation.Operator']: filter.secondOperation.operator,
            ['SecondOperation.Values']: filter.secondOperation.values
        },
    },
    { apiName: this.apiName });

If the errors disappear that way, please let us know.

mehmet-erim avatar Aug 31 '21 09:08 mehmet-erim

Hi, @mehmet-erim I replaced and it works, the errors disappeared. Also, I tested it with a debug break-point in the baking api service, and it works, the Input Dto was sent correctly.

nev-21 avatar Sep 01 '21 00:09 nev-21

We will handle that case on the ABP schematics to fix the problem. Thanks for the reporting!

mehmet-erim avatar Sep 01 '21 09:09 mehmet-erim

Thanks @mehmet-erim

nev-21 avatar Sep 01 '21 09:09 nev-21