title: ngx-dropzone-wrapper + .NET Core Web API
body: <p>For some reason my collection of IFormFiles is always empty when sending files from my Angular 5 application to my .NET Core Web API. I'm guessing I'm just over looking a configuration somewhere. Does anyone see anything wrong with this? Note that I'm using ngx-dropzone-wrapper (<a href="https://github.com/zefoy/ngx-dropzone-wrapper" rel="nofollow noreferrer">https://github.com/zefoy/ngx-dropzone-wrapper</a>). Thanks in advance!</p>
  
  <p><strong>home.component.html</strong></p>
  
  <pre><code>&lt;!-- Container --&gt;
  &lt;div class="container"&gt;
      &lt;form&gt;
          &lt;dropzone class="dropzone-container" [message]="'Click or drag groups of files to upload them to the Data Entry API'" (error)="uploadError($event)"
              (success)="uploadSuccess($event)" (queueComplete)="complete($event)" (sending)="sending($event)"&gt;
          &lt;/dropzone&gt;
          &lt;button (click)="processQueue()"&gt;Go&lt;/button&gt;
      &lt;/form&gt;
  &lt;/div&gt;
  &lt;!-- End Container --&gt;
  </code></pre>
  
  <p><strong>home.component.ts</strong></p>
  
  <pre><code>import { Component, ViewEncapsulation, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
  import { DropzoneComponent, DropzoneDirective, DropzoneConfigInterface } from 'ngx-dropzone-wrapper';
  import { DataEntryService } from '../../services/data-entry.service';
  import Swal from 'sweetalert2'
  
  @Component({
    selector: 'app-home',
    templateUrl: './home.component.html',
    styleUrls: ['./home.component.scss'],
    encapsulation: ViewEncapsulation.None
  })
  export class HomeComponent implements AfterViewInit {
  
    // References to the dropzone component
    @ViewChild(DropzoneComponent) componentRef: DropzoneComponent;
    dropzone: any;
  
    // Flag to determine whether or not the 'Yes' button should be shown
    uploading: boolean = false;
  
    //** Constructor */
    constructor(private _dataEntryService: DataEntryService) { }
  
    /** Lifecycle hook that is called after a this component's view has been fully initialized */
    ngAfterViewInit() {
  
      // Get a reference ot the dropzone component
      this.dropzone = this.componentRef.directiveRef.dropzone();
    }
  
    /** 
     * Sends all queued files to our API (not the Data Entry API)
     * Triggered when the user clicks the 'Yes' button
     * @returns {void}
     * */
    processQueue(): void {
  
      console.log('Processing the queue');
  
      this.dropzone.processQueue();
    }
  
    /** 
     * Gets the xhr object and the formData objects as second and third parameters, so they can be modified or additional data can be added
     * Triggered by dropzone just before each file is sent
     * @param {any} args - The dropzone arguments
     * @returns {void}
     * */
    sending(args: any): void {
  
      console.log('Sending files');
      console.log(args);
    }
  
    /** 
     * Displays an error messages if one or more files were rejected by dropzone
     * Triggered by dropzone when an upload was either successfull or erroneous
     * @param {any} args - The dropzone arguments
     * @returns {void}
     * */
    complete(args: any): void {
  
      console.log('File upload comlpete');
  
      let accepted = this.dropzone.getAcceptedFiles();
      let rejected = this.dropzone.getRejectedFiles();
      let queued = this.dropzone.getQueuedFiles();
      let uploading = this.dropzone.getUploadingFiles();
  
      console.log('Accepted:  ' + accepted.length);
      console.log('Rejected:  ' + rejected.length);
      console.log('Queued:  ' + queued.length);
      console.log('Uploading:  ' + uploading.length);
  
      if (queued.length === 0 &amp;&amp; uploading.length === 0) {
  
        if (rejected.length &gt; 0) {
  
          Swal({
            type: 'error',
            title: 'Rejected Files',
            text: rejected.length + ' of the files that you uploaded were rejected. Please close this modal, correct your errors and try again.'
          });
  
          this.uploading = true;
        }
      }
    }
  
    /** 
     * For now, this just writes success messages to the console for debugging purposes
     * Triggered when a file has been uploaded successfully
     * @param {any} args - The dropzone arguments
     * @returns {void}
     * */
    uploadSuccess(args: any): void {
  
      console.log('Upload successful');
  
      if (args &amp;&amp; args[0]) {
        console.log('File Uploaded:  ' + args[0].name);
      }
    }
  
    /** 
   * For now, this just writes error messages to the console for debugging purposes
   * Triggered when an upload error occurs
   * @param {any} args - The dropzone arguments
   * @returns {void}
   * */
    uploadError(args: any): void {
  
      console.error('Upload Error');
  
      if (args &amp;&amp; args[1]) {
        console.error(args[1]);
      }
    }
  
  }
  </code></pre>
  
  <p><strong>config</strong></p>
  
  <pre><code>const DEFAULT_DROPZONE_CONFIG: DropzoneConfigInterface = {
  
    // Where we should send the files (Default: null)
    url: 'http://localhost:61143/api/xray',
  
    // Whether the queue will be processed automatically
    autoProcessQueue: false,
  
    // Optional oject to send additional headers to the server (Default: null)
    headers: null,
  
    // How many file uploads to process in parallel (Default: null)
    parallelUploads: 500,
  
    // Name of the file parameter that gets transferred (Default: 'file')
    paramName: 'file',
  
    // Maximum file size for the upload files in megabytes (Default: null)
    maxFilesize: 500,
  
    // Comma separated list of mime types or file extensions (Default: null)
    acceptedFiles: '.jpg, .dcm, .dicom',
  
    // Whether to send multiple files in one request (Default: null)
    uploadMultiple: true,
  
    // Whether thumbnails for images should be generated
    createImageThumbnails: false,
  
    // Whether to add a link to every file preview to remove or cancel (if already uploading) the file
    addRemoveLinks: true
  };
  </code></pre>
  
  <p><strong>.NET Core Web API Controller</strong></p>
  
  <pre><code>using System.Linq;
  using Microsoft.AspNetCore.Mvc;
  using DataEntry.Data;
  using System;
  using Microsoft.AspNetCore.Http;
  using System.Collections.Generic;
  
  namespace DataEntry.API.Controllers
  {
      [Produces("application/json")]
      [Route("api/xray")]
      public class XRayController : Controller
      {
          private readonly DataEntryContext _db;
  
          public XRayController(DataEntryContext db)
          {
              _db = db;
          }
  
          // POST: api/xray
          [HttpPost]
          public IActionResult AddXRay(ICollection&lt;IFormFile&gt; files)
          {
              try
              {
                  if (files == null || files.Count == 0)
                  {
                      // Always 0 files here
                      throw new Exception("One or more JPG or DICOM file is required to upload X-rays.");
                  }
  
                  return Ok();
              }
              catch (Exception ex)
              {
                  return BadRequest(ex.Message);
              }
          }
      }
  }
  </code></pre>