8 Answer(s)
-
0
The ABP Angular service proxy generator does not currently generate the type alias
export type StringValues = string[];
automatically for DTOs that use types likeIFormFile
with properties such asheaders: 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.
-
0
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>
<!-- Upload-Button --> <button class="btn btn-primary mt-3" [disabled]="!selectedFile || isUploading" (click)="uploadFile()"> <i class="fa fa-upload me-1"></i> <span *ngIf="!isUploading">Hochladen</span> <span *ngIf="isUploading">Wird hochgeladen...</span> </button> <!-- Erfolgsmeldung --> <div *ngIf="uploadResult" class="alert alert-success mt-3"> Upload erfolgreich! Neue Version: {{ uploadResult.versionNr }} (ID: {{ uploadResult.id }}) </div>
</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
-
0
hi
Please use
IRemoteStreamContent
to replaceIFormFile
in your DTO and regenerate the Angular proxy.https://abp.io/docs/latest/framework/architecture/domain-driven-design/application-services#working-with-streams
Thanks.
-
0
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.
-
0
hi
I will ask our Angular team asap.
Thanks.
-
0
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:
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
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.
-
0
-
0
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:
Sending
FormData
input in such a waypublic readonly proxyService = inject(FirstEntityService); // ... protected createFileRequest(file) { formData.append('File', file); formData.append('itemId', '21902787'); formData.append('tenantId', '7872091221902787'); return this.proxyService.uploadFile(formData); }
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.