Angular/Web API:将FormFile信息从客户端发送到API
我正在努力在Angular应用程序中创建一个包含0-n个子对象(文件“附件”)的对象(“票证”),并将信息发送到我的dotnet core Web Api。但这是一个更符合逻辑的问题 当用户创建票据时,他应该能够向该票据添加附件 关于如何上传文件的文章很多,但我不想看到的是,用户在创建票据时上传附件。我不想这样做,因为如果用户取消票证创建,我的存储(Azure)中将有未使用的附件,如果没有对entity framework服务器端的票证TID(这次不存在)的引用,我将无法创建附件对象 所以我喜欢先收集所有信息,如果用户说“创建票证”,所有信息都会发送到APIAngular/Web API:将FormFile信息从客户端发送到API,angular,asp.net-web-api,.net-core,asp.net-core-webapi,Angular,Asp.net Web Api,.net Core,Asp.net Core Webapi,我正在努力在Angular应用程序中创建一个包含0-n个子对象(文件“附件”)的对象(“票证”),并将信息发送到我的dotnet core Web Api。但这是一个更符合逻辑的问题 当用户创建票据时,他应该能够向该票据添加附件 关于如何上传文件的文章很多,但我不想看到的是,用户在创建票据时上传附件。我不想这样做,因为如果用户取消票证创建,我的存储(Azure)中将有未使用的附件,如果没有对entity framework服务器端的票证TID(这次不存在)的引用,我将无法创建附件对象 所以我喜欢
export interface ITicketCreate {
subject: string;
content: string;
category: number;
userId: string;
userNickname: string;
email: string;
attachments: File[];
}
发送到Api的最终Dto对象如下所示:
export interface ITicketCreate {
subject: string;
content: string;
category: number;
userId: string;
userNickname: string;
email: string;
attachments: File[];
}
具有createTicket功能的服务
export class SupportService {
supportUrl = environment.SupportApiUrl;
constructor(private http: HttpClient) { }
createTicket(model: ITicketCreate) {
return this.http.post(this.supportUrl + 'tickets', model);
}
...
}
以及CreateTicketComponent中的调用
ticket = {} as ITicketCreate;
...
ngOnInit() {
this.ticket.attachments = [];
}
createTicket() {
console.log(this.ticket);
this.ticket.userId = this.authService.currentUser.id;
this.ticket.userNickname = this.authService.currentUser.nickName;
this.ticket.email = this.authService.currentUser.userName;
this.supportService.createTicket(this.ticket).subscribe(next => {
this.alertify.success('Ticket created');
this.router.navigate(['/support/tickets']);
}, error => {
this.alertify.error(error);
console.log(error);
});
}
Web Api(.Net Core 2.2)
在服务器端,我有以下Dto来接收数据:
public class CreateTicketDto
{
public string Subject { get; set; }
public string Content { get; set; }
public string UserId { get; set; }
public string Email { get; set; }
public string UserNickname { get; set; }
public int Category { get; set; }
public List<IFormFile> Attachments { get; set; } = new List<IFormFile>();
}
public类CreateTicketDto
{
公共字符串主题{get;set;}
公共字符串内容{get;set;}
公共字符串用户标识{get;set;}
公共字符串电子邮件{get;set;}
公共字符串用户昵称{get;set;}
公共int类{get;set;}
公共列表附件{get;set;}=new List();
}
以及控制器的动作
[HttpPost]
public async Task<IActionResult> CreateTicket(CreateTicketDto createTicket)
[HttpPost]
公共异步任务CreateTicket(CreateTicket到CreateTicket)
发送请求后,我从API中得到的错误是:
由于我不是为了调试而输入控制器操作本身,我的问题是:
Kay实际的错误消息告诉您无法实例化接口/抽象类。这是正常的,因为不能实例化接口或抽象类,所以需要非抽象类来实例化它。因此,您需要检查这一行
public List<IFormFile> Attachments { get; set; } = new List<IFormFile>();
公共列表附件{get;set;}=new List();
并查看是否可以通过使用IFormFile接口的完整实现类来消除障碍,以便在尝试添加附件时不会出现此错误
至于你的实际问题,你有几个选择:
不允许在插入时上载附件
这是一个简单的想法。在“添加”模式下,您不显示任何附件,也不允许上载文件,但在“编辑”模式下,您允许上载文件。您可以显示文件上载部分的禁用版本,并确保在服务器端不存储任何尝试的上载
有两个单独的表单用于票据上传和文件上传
在这种情况下,您将显示所有情况下的所有内容,甚至允许准备上载文件,但仅在实际创建了票证时才允许上载附件
使用proto类获取票证
您可以为票证实现一个proto类,因此,如果票证尚未创建,但发送了附件,则将使用创建它的用户的外键创建一个ProtoTicket,因此您将跟踪附件,并允许用户在实际创建票证之前上载附件。下次用户创建票证时,他/她与proto票证的所有附件都将与该新票证关联,并且proto票证将被删除。你也可以定期清理原始票。我认为这是最好的解决方案,因为它提供了最好的UX并保护您的服务器免受垃圾文件的侵害。新年快乐!