Send both file and model data using AngularJS with FormData

When uploading an image using the file input type along with other user data, my model includes the User class:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Rollno { get; set; }
    public byte[] ProfileImage { get; set; }
    public HttpPostedFile image { get; set; }
}

And a method posted in ASP.NET MVC:

public ActionResult AddUser(User user)
{
    var files = Request.Files;
    foreach (string fileName in Request.Files)
    {
        HttpPostedFileBase file = Request.Files[fileName];
        byte[] uploadFile = new byte[file.InputStream.Length];

    }
    return View();
}

An example of the input tag being used:

<input id="imgInp" type="file" aria-label="Add photos to your post" class="upload" name="file" onchange="angular.element(this).scope().LoadFileData(this.files)" multiple="" accept="image/*">

With an AngularJS controller that looks like this:

angular.module('app', ['AngularDemo.BeerController']).
  controller('formController',['$scope','$http', function ($scope,$http) {
    alert('in controller');
    var formData = new FormData();

    $scope.LoadFileData = function (files) {
        for (var file in files) {
            formData.append("file", files[file]);
        }
    };

    $scope.submit = function () {

        alert('in submit');
        $http.post("/Home/AddUser", formData, {
            withCredentials: true,
            headers: { 'Content-Type': undefined },
            transformRequest: angular.identity
        }).success(function (response) {

        });
    }
}]);

The image file is successfully posting back in the AddUser method, but I am unsure how to send the model data. I have added ng-model="Name" etc in the form. How do I also send $scope.Name, along with the image data since my $http.post expects form data?

Answer №1

After some troubleshooting, I managed to resolve the issue. It turns out that the return statement was missing in the code snippet.

.controller('formController',['$scope','$http', function ($scope, $http) {
    $scope.user = {
        Id: 0,
        Name: ""
    };
    $scope.files = [];

    $scope.LoadFileData = function(files) {
        $scope.files = files;
    };

    $scope.submit = function() {
        $http({
            url: "/Home/AddUser",
            method: "POST",
            headers: { "Content-Type": undefined },
            transformRequest: function(data) {
                var formData = new FormData();
                formData.append("user", angular.toJson(data.user));
                for (var i = 0; i < data.files.length; i++) {
                    formData.append("files[" + i + "]", data.files[i]);
                }
                *return formData;*//NOTICE THIS RETURN WHICH WAS MISSING
            },
            data: { user: $scope.user, files: $scope.files }
        })
        .success(function(response) {   });
    };
});

Answer №2

To make this function, you can convert User into a JSON string. However, keep in mind that this method will not link the image properties of the User class.

[HttpPost]
public ActionResult AddUser(string user, HttpPostedFileBase[] files)
{
    // convert user into User object
}

Field entries

<input id="imgInp" type="file" aria-label="Add photos to your post" class="upload" name="file"
       onchange="angular.element(this).scope().LoadFileData(this.files)" multiple="" accept="image/*">
<input name="Id" type="text" ng-model="user.Id" />
<input name="Name" type="text" ng-model="user.Name" />

Additionally, here is the Angular controller code:

.controller('formController',['$scope','$http', function ($scope, $http) {
    $scope.user = {
        Id: 0,
        Name: ""
    };
    $scope.files = [];

    $scope.LoadFileData = function(files) {
        $scope.files = files;
    };

    $scope.submit = function() {
        $http({
            url: "/Home/AddUser",
            method: "POST",
            headers: { "Content-Type": undefined },
            transformRequest: function(data) {
                var formData = new FormData();
                formData.append("user", angular.toJson(data.user));
                for (var i = 0; i < data.files.length; i++) {
                    formData.append("files[" + i + "]", data.files[i]);
                }
            },
            data: { user: $scope.user, files: $scope.files }
        })
        .success(function(response) {   });
    };
});

If you prefer not to convert JSON to User, then you may need to create a custom binder. For simpler cases with few user fields, passing them as separate parameters could be an alternative:

public ActionResult AddUser(string userName, int userId, HttpPostedFileBase[] files) { ... }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm looking to replicate this navigation layout using Vuetify's 'navigation drawer' component. How can I go about doing this?

I'm currently utilizing Vuetify and implementing the Navigation Drawer component. I am attempting to replicate a similar navigation layout found here. The fixed menu on the left should maintain its width even when resizing the browser window. Upon ...

Filtering JSON objects within nested objects using Angular

I'm facing an issue while attempting to filter my data based on the routeparam. It seems like the problem might be stemming from the structure of my JSON. Angular doesn't seem to be able to filter objects within objects. Is there a custom filter ...

What am I doing wrong that causes me to repeatedly run into errors when trying to build my react app?

While attempting to set up a react.js web application in VScode using "npm," I encountered the following errors: npm ERR! code ERR_SOCKET_TIMEOUT npm ERR! errno ERR_SOCKET_TIMEOUT npm ERR! network Invalid response body while trying to fetch https://registr ...

Troubleshooting: Inoperative AngularJS buttons with ng-click

Learning AngularJS has been an exciting journey for me. I'm experimenting with toggling a modal by using ng-if and ng-click. Basically, in my controller, I've defined a scoped variable called "aboutOn". If it's true, the modal is displayed; ...

The initial row of data does not appear to be exported in the CSV file when using the ng-table-export feature in AngularJS

I have integrated ng-table-export into my project, but I am facing an issue where the first row records are missing when I export the data. Below is a screenshot and snippet of my code, can someone please provide assistance? User Interface Output Exporte ...

Struggling with integrating API response formatting in React and updating state with the data

This is the content found in the file 'Search.js' import React, { Component } from 'react'; import * as BooksAPI from './BooksAPI' class Search extends Component{ constructor(props){ super(props); this.state={ ...

Quick question about utilizing Ajax with spans

<span name = "menu"> <!-- javascript here --> <!-- content loaded via ajax --> </span> <span name = "content"> <!-- content loaded via ajax --> <!-- updated by buttons from the menu--> </span> Seeking a ...

The compatibility issue between Angular JS App and JSPDF is causing malfunctions specifically in Internet Explorer

I am currently working on an Angular JS application that utilizes JSPDF for generating PDFs. While the PDF generation functionality works perfectly fine on Chrome, Firefox, and Safari, it encounters issues on Internet Explorer (IE). The specific error mes ...

Launch the game within the gaming application

I am looking to incorporate a game within another game... Here's what I mean: Open the app: Pandachii Next, navigate to the 4th button (game pad). When we click on the game icon, I want to launch another game (located below the Pandachii window - c ...

No results returned by Mongoose/MongoDB GeoJSON query

I have a Schema (Tour) which includes a GeoJSON Point type property called location. location: { type: { type: String, enum: ['Point'], required: true }, coordinates: { type: [Number], required: true ...

Swapping data between two HTML files and PHP

As I work on setting up a signup form for a MikroTik hotspot, I've encountered limitations with the device not supporting PHP. In order to pass the necessary variables from the device to an external PHP page where customer data will be saved and trial ...

Configuring Multer destination dynamically using FormData values in Node.js

I have a scenario where I need to send a file along with some data values using an XMLHttpRequest (xhr) to a Node.js server running Express. To handle multipart data, I am utilizing Multer as bodyParser does not work in this case. router.post("/submit", f ...

Retrieving device information through JavaScript, jQuery, or PHP

Looking to build a website that can identify the device name and model of visitors accessing the page from their devices. ...

Obtaining the clicked element within a functional component in React

I'm having trouble in React because I am unable to select the clicked element. The use of "this" in a functional component is not functioning as expected. function Test(data) { function getElement() { } return ( <div> ...

The Jquery .clone() function presents issues in Internet Explorer and Chrome browsers, failing to perform as expected

I need to duplicate an HTML control and then add it to another control. Here is the code I have written: ko.bindingHandlers.multiFileUpload = { init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { va ...

Intersecting table columns with a different data table

My task is to create a table with a column that contains another table, where I want the colors of each alternating row to be different. Please refer to the image below (ignore the "CharacterAgain" column). Below is an example of AngularJS code for the ta ...

Looping through jQuery, I am adding divs, but frustratingly I can only insert text into the initial div created. Why

var numPills = 3 for(var i=0; i< numPills; i++){ //var currentPill = JUser.pill1.; $(".col-r-in").append( $('<div/>') .attr("id", "medsProgress") .addClass("roundedBar") ); $('#medsProgress').append( $('<div/>&apo ...

error detection in AJAX response handler

My web-application was created using PHP, AJAX, and jQuery, and the development process went smoothly. The majority of the requests to the application are made via AJAX for operations such as insert, update, delete, and select. I have already implemented ...

There was an error thrown: [vuex] getters must be defined as a function, however, the getter "getters.default" is an empty

After building my VUE project for production with NPM, I encountered an error in the console. Can anyone shed some light on why vuex is presenting this complaint? npm 3.10 , node.js 8.11 Uncaught Error: [vuex] getters should be function but "getters.defau ...

Refresh an Angular page automatically

Having a small issue in my angular application. The problem arises on the first page where I display a table listing all employees along with a "Create New Employee" button that opens a form for adding a new employee. However, after submitting the form and ...