Angular / Web API:将FormFile信息从客户端发送到API

时间:2019-12-28 11:54:48

标签: angular asp.net-web-api .net-core asp.net-core-webapi

我正在为在Angular应用程序中创建具有0-n个子对象(文件“附件”)的对象(“票证”)并将信息发送到我的dotnet核心Web Api而苦苦挣扎。但这是一个更合理的问题。

用户创建工单时,他应该能够向该工单添加附件。

关于如何上传文件的文章很多,但我不需要的是,用户在创建工单时上传附件。我不希望这样,因为如果用户取消票证的创建,则存储区(Azure)中将有未使用的附件,并且如果没有对TicketId的引用(这一次不存在),我将无法创建附件对象)在服务器端使用实体框架。

所以我想先收集所有信息,如果用户说“创建票证”,所有信息将发送到API,

  1. 将创建票证对象
  2. 文件将根据FILE信息上传(到Azure)
  3. 已创建附件对象
  4. 将附件对象添加到故障单中,并且
  5. 所有内容都保存到数据库

Angular(客户端)

用于收集票证数据并选择附件文件的表格。界面如下所示:

export interface ITicketCreate {
    subject: string;
    content: string;
    category: number;
    userId: string;
    userNickname: string;
    email: string;
    attachments: File[];
}

发送到Api的最终Dto对象如下所示:

enter image description here

带有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>();
}

和控制器动作

[HttpPost]
public async Task<IActionResult> CreateTicket(CreateTicketDto createTicket)

发送请求后,我从API得到的错误是:

enter image description here

由于我没有进入控制器动作本身就无法进行调试,所以我的问题是:

  1. 我喜欢这样工作吗?
  2. 如果是,我想念什么?

最好的问候, 凯

1 个答案:

答案 0 :(得分:1)

实际的错误消息告诉您无法实例化接口/抽象类。这是正常现象,因为您无法实例化接口或抽象类,因此需要非抽象类来实例化它。因此,您需要查看此行

public List<IFormFile> Attachments { get; set; } = new List<IFormFile>();

并查看是否可以通过使用IFormFile接口的完整实现类来消除障碍,因此,当尝试添加附件时,不会出现此错误。

关于您的实际问题,您有几种选择:

禁止插入附件上传

这是一个简单的想法。在添加模式下,您只是不显示任何附件,并且不允许上传文件,但是在编辑时,您可以允许它。您可以显示文件上传部分的禁用版本,并确保在服务器端不存储任何尝试的上传。

对于票证上传和文件上传有两种不同的形式

在这种情况下,您将在所有情况下显示所有内容,甚至允许准备上传文件,但仅在实际创建票证的情况下才允许上传附件

对门票使用原型班级

您可以为票证实现一个原型类,因此,如果尚未创建票证,但是发送了附件,则将创建一个ProtoTicket,并为其创建用户提供外键。附件,并允许用户在实际创建票证之前上传附件。在下一次用户创建票证时,他/她对原始票证的所有附件都将与该新票证关联,并且原始票证将被删除。您也可以定期清理原始票证。我认为这是最好的解决方案,因为它可以提供最佳的UX,并保护服务器免受垃圾文件的侵害。