Open Closed

[BUG] - "export type StringValues = string[];" missing #9641


User avatar
0
starting created

Automapper does not generate "export type StringValues = string[];"

Everytime I regenerate that proxy, I need to add that line

That is the DTO


8 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • The ABP Angular service proxy generator does not currently generate the type alias export type StringValues = string[]; automatically for DTOs that use types like IFormFile with properties such as headers: Record<string, StringValues>. This is a known limitation.

    • As a workaround, you need to manually add export type StringValues = string[]; to your generated proxy files after each regeneration.

    • This issue is related to how the proxy generator handles certain .NET types and their translation to TypeScript. There is an open issue for similar proxy generation problems:

      • https://github.com/abpframework/abp/issues/18932
    • For more details on Angular service proxy generation, see the official documentation:

      • https://abp.io/docs/latest/UI/Angular/Service-Proxies

    Currently, there is no built-in way to customize or extend the proxy generator to automatically include this type alias. You may consider scripting this addition as part of your build process until the generator is improved.

    Sources:

    • https://github.com/abpframework/abp/issues/18932
    • https://abp.io/docs/latest/UI/Angular/Service-Proxies

    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.

  • User Avatar
    0
    starting created

    The upload doesnt work, I always get

    with that "import { ToasterService } from '@abp/ng.theme.shared'; import { Component, Input } from '@angular/core'; import { SchemaDto, SchemaService, UploadSchemaDto } from '@proxy/-my-structure'; import { FallAuswahlStateService } from '../fall-auswahl/fall-auswahl-state.service'; import { finalize } from 'rxjs';

    @Component({ selector: 'app-schema-upload', standalone: false, templateUrl: './schema-upload.component.html', styleUrls: ['./schema-upload.component.scss'], }) export class SchemaUploadComponent { @Input() itemId: string;

    selectedFile: File | null = null; isUploading = false; uploadResult: SchemaDto | null = null;

    constructor( private schemaService: SchemaService, private toaster: ToasterService, private state: FallAuswahlStateService ) {}

    onFileSelected(event: Event): void { const element = event.currentTarget as HTMLInputElement; const fileList: FileList | null = element.files; if (fileList && fileList.length > 0) { this.selectedFile = fileList[0]; this.uploadResult = null; } } uploadFile(): void { if (!this.selectedFile || !this.itemId) { this.toaster.error('Bitte wählen Sie eine Datei aus und stellen Sie sicher, dass eine Item-ID vorhanden ist.', 'Validierungsfehler'); return; }

    this.isUploading = true; this.uploadResult = null;

    const input: UploadSchemaDto = { file: this.selectedFile as any, itemId: this.itemId };

    this.schemaService.uploadSchema(input) .pipe( finalize(() => { this.isUploading = false; }) ) .subscribe({ next: (result) => { this.uploadResult = result as any; this.toaster.success('Schema erfolgreich hochgeladen.', 'Erfolg'); this.selectedFile = null; }, error: (err) => { console.error('Upload fehlgeschlagen:', err); this.toaster.error('Der Upload ist fehlgeschlagen.', 'Fehler'); } }); }

    private resetFormInput(): void { const fileInput = document.getElementById('schemaFile') as HTMLInputElement; if (fileInput) { fileInput.value = ''; } this.selectedFile = null; } }"

    and

    "<div class="card"> <div class="card-header"> <h3>Schema für Item hochladen</h3> </div> <div class="card-body"> <!-- File-Input --> <div class="form-group"> <label for="schemaFile">Excel-Datei auswählen (.xlsx, .xls, .xlsm)</label> <input type="file" id="schemaFile" class="form-control-file" (change)="onFileSelected($event)" accept=".xlsx, .xls, .xlsm" /> </div>

    &lt;!-- Upload-Button --&gt;
    &lt;button 
      class=&quot;btn btn-primary mt-3&quot; 
      [disabled]=&quot;!selectedFile || isUploading&quot;
      (click)=&quot;uploadFile()&quot;&gt;
      &lt;i class=&quot;fa fa-upload me-1&quot;&gt;&lt;/i&gt;  
      &lt;span *ngIf=&quot;!isUploading&quot;&gt;Hochladen&lt;/span&gt;
      &lt;span *ngIf=&quot;isUploading&quot;&gt;Wird hochgeladen...&lt;/span&gt;
    &lt;/button&gt;
    
    &lt;!-- Erfolgsmeldung --&gt;
    &lt;div *ngIf=&quot;uploadResult&quot; class=&quot;alert alert-success mt-3&quot;&gt;
      Upload erfolgreich! Neue Version: {{ uploadResult.versionNr }} (ID: {{ uploadResult.id }})
    &lt;/div&gt;
    

    </div> </div>"

    that is the configuration:

    "

    • Template: app
    • Created ABP Studio Version: 0.9.25
    • Current ABP Studio Version: 1.0.2
    • Tiered: Yes
    • Multi-Tenancy: Yes
    • UI Framework: angular
    • Theme: leptonx
    • Theme Style: system
    • Run Install Libs: Yes
    • Progressive Web App: No
    • Run Progressive Web App Support: No
    • Database Provider: ef
    • Database Management System: sqlserver
    • Separate Tenant Schema: Yes
    • Create Initial Migration: Yes
    • Run Db Migrator: Yes
    • Mobile Framework: none
    • Public Website: No
    • Include Tests: Yes
    • Kubernetes Configuration: Yes
    • Distributed Event Bus: none
    • Use Local References: No
    • Optional Modules:
      • GDPR
      • FileManagement
      • TextTemplateManagement
      • LanguageManagement
      • AuditLogging
      • OpenIddictAdmin

    "

    the appservice method

    I changed the proxy (!manually):

    and the upload method

    and now its working!

    But this is not practical. Please give me the full code

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please use IRemoteStreamContent to replace IFormFile in your DTO and regenerate the Angular proxy.

    https://abp.io/docs/latest/framework/architecture/domain-driven-design/application-services#working-with-streams

    Thanks.

  • User Avatar
    0
    starting created

    I added:

    My AppService:

    This is the backend

    And frontend:

    The generated proxy:

    I get the same error:

    The values are filled

    The proxy is generated wrong:

    Please give me a fast workaround

    The issue is a mismatch between the client's request and the server's expectation. Since the server is following the correct and most efficient standard, the solution is to fix the client to match the server, not the other way around.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I will ask our Angular team asap.

    Thanks.

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello,

    Thank you for providing such detailed information. After reviewing the section where you appended values to the FormData while modifying the proxy, I noticed that you are trying to work with an object on the backend. You can still achieve this functionality without altering the current proxy setup.

    These resources might be helpful:

    1. How to Upload and Download Files in ABP: https://abp.io/community/articles/how-to-upload-and-download-files-in-the-abp-framework-using-angular-que8cdr8#gsc.tab=0

    2. Using append() with FormData (MDN): https://developer.mozilla.org/en-US/docs/Web/API/FormData/append

    Feel free to reach out if you need further assistance.

  • User Avatar
    0
    starting created

    So its still a bug, that the automapper is not generating

    And its not working

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Yes, you are right the proxy generation creates such functions by just checking the backend implementation. For your case, everything should be clear other than the generated uploadSchema function.

    I can recommend you to have such approach:

    1. Sending FormData input in such a way

        public readonly proxyService = inject(FirstEntityService);
      
      	// ...
      
        protected createFileRequest(file) {
      
          formData.append('File', file);
          formData.append('itemId', '21902787');
          formData.append('tenantId', '7872091221902787');
      
          return this.proxyService.uploadFile(formData);
      
        }
      
      
    2. Modifying the uploadFile function in the proxy as follows:

      export class FirstEntityService {
      	// ...
        uploadFile = (input: FormData, config?: Partial<Rest.Config>) =>
          this.restService.request<any, AppFileDescriptorDto>(
            {
              method: 'POST',
              url: '/api/app/first-entities/upload-file',
              body: input,
            },
            { apiName: this.apiName, ...config }
          );
      }
      
      

    I can share a sample project if you would like to. You can also let us know if you need further assistance. Thank you for your cooperation.

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.0.0-preview. Updated on September 01, 2025, 08:37