如何使用 kendo-fileselect 从 angular 应用程序上传到 C# web API?
How can you use kendo-fileselect to upload from an angular app to a C# web API?
我们正在项目中为 angular 实施 kendo。我们有一个使用 kendo-upload 的现有项目,它会立即触发对服务器的调用,但我不能为此页面执行此操作。
该页面供员工上传简历。他们可能有一份现有的简历,需要先询问他们是否要替换它,然后他们会得到一个用于输入描述的字段。因此,我认为我需要使用 kendo-fileselect 并可能触发一个对话框(您确定要替换吗?),然后在单击按钮时发送描述和员工 ID。所以我创建了一个对象来携带这些数据。
您可以看到对象在调用 API:
时被填充
但是当我尝试调用 API 方法时,出现错误:
Failed to load resource: the server responded with a status of 400 (Bad Request) [http://localhost:6300/api/employee/resume]
相关代码如下
服务器端:
public class EmployeeResume
{
public int ResumeId { get; set; }
public int EmployeeId { get; set; }
public DateTime CreatedDate { get; set; }
public string Description { get; set; }
public byte[] FileContent { get; set; }
public string FileName { get; set; }
}
[HttpPut("resume")]
public async Task<IActionResult> UploadResume([FromBody] EmployeeResume resume)
{
if (resume == null)
{
return BadRequest();
}
return Ok();
}
客户端:
// Model
export interface EmployeeResume {
createdDate?: string;
description?: string;
employeeId: string;
fileContent: any;
fileName: string;
resumeId?: string;
}
// CHILD component
// -----------------------------------------------------------
// Kendo FileSelect in template
<kendo-fileselect
formControlName="uploadFile"
[restrictions]="uploadRestrictions"
[multiple]="false"
(select)="selectEventHandler($event)">
</kendo-fileselect>
// Sets a component property to the selected file
selectEventHandler(e: SelectEvent): void {
this.uploadfile = e.files[0];
}
// When upload button is clicked, create the
// resume object and emit an event to parent
upload(): void {
if (this.uploadfile.validationErrors) return;
const thisComponent = this;
const reader = new FileReader();
reader.onload = function (ev) {
const request = {
description: thisComponent.f.description.value,
employeeId: thisComponent.employeeId,
fileContent: ev.target.result,
fileName: thisComponent.uploadfile.name
} as EmployeeResume;
thisComponent.onUpload.emit(request);
}
reader.readAsDataURL(this.uploadfile.rawFile);
}
// PARENT component
// -----------------------------------------------------------
// Template
<app-employee-resume
[employeeId]="(employeeId$ | async)"
(onUpload)="uploadResume($event)">
</app-employee-resume>
// Handler
uploadResume(resume: EmployeeResume) {
this.svc.upsertResume(resume)
}
// 'svc'
upsertResume(resume: EmployeeResume) {
return this.http.put(`${this.apiUrl}/employee/resume`, resume);
}
您可以使用 ts FormData 和自定义 FileData 对象以及您想要存储到数据库的任何额外属性:
onFileSelected(e: SelectEvent): void {
this.uploadfile = e.files[0].rawFile;
}
upload(): void {
const formData = new FormData();
const fileForSave = new FileData();
fileForSave.fileCategoryId = FileCategory.EmployeeResume;
fileForSave.description = this.f['description'].value;
fileForSave.employeeId = this.employeeId;
if (this.uploadfile) formData.append('file', this.uploadfile);
formData.append('fileForSave', JSON.stringify(fileForSave));
this.onUpload.emit(formData);
this.resetForm();
}
addFile(form: FormData): Observable<FileData> {
return this.http.post<FileData>(`${this.apiUrl}/file/`, form);
}
那么您的 API 方法将如下所示:
[HttpPost]
public async Task<IActionResult> AddFile(
IFormFile file,
[ModelBinder(BinderType = typeof(JsonModelBinder))] Contracts.Entities.File fileForSave)
{
// Check any file validations if you want
/* Save the IFormFile file to disk */
/* Save entity fileForSave File object to the DB */
return Ok(newFile);
}
我什至会把这个扔给你:
public class JsonModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// Check the value sent in
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult != ValueProviderResult.None)
{
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
// Attempt to convert the input value
var valueAsString = valueProviderResult.FirstValue;
var result = Newtonsoft.Json.JsonConvert.DeserializeObject(valueAsString, bindingContext.ModelType);
if (result != null)
{
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
return Task.CompletedTask;
}
}
我们正在项目中为 angular 实施 kendo。我们有一个使用 kendo-upload 的现有项目,它会立即触发对服务器的调用,但我不能为此页面执行此操作。
该页面供员工上传简历。他们可能有一份现有的简历,需要先询问他们是否要替换它,然后他们会得到一个用于输入描述的字段。因此,我认为我需要使用 kendo-fileselect 并可能触发一个对话框(您确定要替换吗?),然后在单击按钮时发送描述和员工 ID。所以我创建了一个对象来携带这些数据。
您可以看到对象在调用 API:
时被填充但是当我尝试调用 API 方法时,出现错误:
Failed to load resource: the server responded with a status of 400 (Bad Request) [http://localhost:6300/api/employee/resume]
相关代码如下
服务器端:
public class EmployeeResume
{
public int ResumeId { get; set; }
public int EmployeeId { get; set; }
public DateTime CreatedDate { get; set; }
public string Description { get; set; }
public byte[] FileContent { get; set; }
public string FileName { get; set; }
}
[HttpPut("resume")]
public async Task<IActionResult> UploadResume([FromBody] EmployeeResume resume)
{
if (resume == null)
{
return BadRequest();
}
return Ok();
}
客户端:
// Model
export interface EmployeeResume {
createdDate?: string;
description?: string;
employeeId: string;
fileContent: any;
fileName: string;
resumeId?: string;
}
// CHILD component
// -----------------------------------------------------------
// Kendo FileSelect in template
<kendo-fileselect
formControlName="uploadFile"
[restrictions]="uploadRestrictions"
[multiple]="false"
(select)="selectEventHandler($event)">
</kendo-fileselect>
// Sets a component property to the selected file
selectEventHandler(e: SelectEvent): void {
this.uploadfile = e.files[0];
}
// When upload button is clicked, create the
// resume object and emit an event to parent
upload(): void {
if (this.uploadfile.validationErrors) return;
const thisComponent = this;
const reader = new FileReader();
reader.onload = function (ev) {
const request = {
description: thisComponent.f.description.value,
employeeId: thisComponent.employeeId,
fileContent: ev.target.result,
fileName: thisComponent.uploadfile.name
} as EmployeeResume;
thisComponent.onUpload.emit(request);
}
reader.readAsDataURL(this.uploadfile.rawFile);
}
// PARENT component
// -----------------------------------------------------------
// Template
<app-employee-resume
[employeeId]="(employeeId$ | async)"
(onUpload)="uploadResume($event)">
</app-employee-resume>
// Handler
uploadResume(resume: EmployeeResume) {
this.svc.upsertResume(resume)
}
// 'svc'
upsertResume(resume: EmployeeResume) {
return this.http.put(`${this.apiUrl}/employee/resume`, resume);
}
您可以使用 ts FormData 和自定义 FileData 对象以及您想要存储到数据库的任何额外属性:
onFileSelected(e: SelectEvent): void {
this.uploadfile = e.files[0].rawFile;
}
upload(): void {
const formData = new FormData();
const fileForSave = new FileData();
fileForSave.fileCategoryId = FileCategory.EmployeeResume;
fileForSave.description = this.f['description'].value;
fileForSave.employeeId = this.employeeId;
if (this.uploadfile) formData.append('file', this.uploadfile);
formData.append('fileForSave', JSON.stringify(fileForSave));
this.onUpload.emit(formData);
this.resetForm();
}
addFile(form: FormData): Observable<FileData> {
return this.http.post<FileData>(`${this.apiUrl}/file/`, form);
}
那么您的 API 方法将如下所示:
[HttpPost]
public async Task<IActionResult> AddFile(
IFormFile file,
[ModelBinder(BinderType = typeof(JsonModelBinder))] Contracts.Entities.File fileForSave)
{
// Check any file validations if you want
/* Save the IFormFile file to disk */
/* Save entity fileForSave File object to the DB */
return Ok(newFile);
}
我什至会把这个扔给你:
public class JsonModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// Check the value sent in
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult != ValueProviderResult.None)
{
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
// Attempt to convert the input value
var valueAsString = valueProviderResult.FirstValue;
var result = Newtonsoft.Json.JsonConvert.DeserializeObject(valueAsString, bindingContext.ModelType);
if (result != null)
{
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
return Task.CompletedTask;
}
}