Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

I have a upload file control that uploads the file data to a MVC Controller . I also want to send additional upload details model object in the same request.

But for file - upload the request content-type undefined works for me. But for the MVC controller to effectively receive the model data it has to be application/json. How would I do that in a single request ?

Or, is there any other approach I can follow ? Please suggest. For the upload to complete I need both the data to be sent to the server.

I am doing is

var formdata;
$scope.getTheFiles = function ($files) {
    formdata = new FormData();
    angular.forEach($files, function (value, key) {
        formdata.append(key, value);
    });

and

$scope.validateFiles = function () {

    var params = UploadDataServices.getGroupMembershipUploadParams();

    $scope.pleaseWait = { "display": "block" };

    var request = {
        method: 'POST',
        url: BasePath + 'uploadNative/ValidateFiles/',
        data: formdata,
        headers: {
            'Content-Type': undefined
        }
    };

    // SEND THE FILES.
    console.log(formdata);

    if (formdata != null || formdata != undefined) {
        $http(request)

And in the MVC controller I get the File Data as

System.Web.HttpFileCollection hfc = System.Web.HttpContext.Current.Request.Files;

Now I want to send that params also in the request which I got via

var params = UploadDataServices.getGroupMembershipUploadParams();

How would I do that ? I tried doing

    var request = {
        method: 'POST',
        url: BasePath + 'uploadNative/ValidateFiles/',
        data: {formdata:formdata,arg:params},
        headers: {
            'Content-Type': undefined
        }
    };

But I could not access the File Data .

Please suggest a way .

Thanks in advance.

share|improve this question

In this way you can upload multiple files along with some properties.

To send multiple files/records using formdata you need to use indexing on the key e.g. [0].someKey i.e. formdata.append('[' + i + '].' + key, value); but if you want to send only one record then you can remove the indexing and pass the key directly into the append function.

When the user clicks on "Add File" button, then a new row is added to the table, user can select a file by clicking the file control and the directive sets the File object onto the controller's scope. When the "Save" button is clicked I am looping through all the files and its properties and appending them to the FormData object and posting it to the controller using a configuration object along with the FormData object.

The model.

public class FileModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public HttpPostedFileBase Attachment { get; set; } // The HttpPostedFileBase provides access to files uploaded by the client.
}

The Action method on MVC Controller

[HttpPost]
public JsonResult SaveFiles(List<FileModel> files)
{
    // Your logic here.
}

The View.

<form role="form" ng-submit="saveFiles()">
    <div class="form-group">
        <table class="table table-bordered table-striped table-responsive">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>File</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-hide="files.length">
                    <td colspan="2">No records to display.</td>
                </tr>

                <tr ng-repeat="file in files">
                    <td>
                        <input type="text" class="form-control" ng-model="file.Name" />
                    </td>
                    <td>
                        <input type="file" class="form-control" file-model="file.Attachment" />
                    </td>
                </tr>
            </tbody>
        </table>
    </div>

    <div class="col-xs-12">
        <div class="col-xs-6">
            <button type="button" class="btn btn-info btn-sm" ng-click="addFile()">Add File</button>
        </div>
        <div class="col-xs-6">
            <button type="submit" class="btn btn-info btn-sm">Save</button>
            <button type="button" class="btn btn-info btn-sm" ng-click="cancelSaveFiles()">Cancel</button>
        </div>
    </div>
</form>

The AngularJS controller.

var app = angular.module('example', []);

app.controller('FilesController', function ($scope) {
    $scope.files = [];
    $scope.saveFiles = saveFiles; // saveFiles func given below.
});

The AngularJS directive for <input type="file" />.

app.directive('fileModel', function ($parse) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                var model = $parse(attrs.fileModel);
                var modelSetter = model.assign;

                element.bind('change', function () {
                    scope.$apply(function () {
                        modelSetter(scope, element[0].files[0]); // sets the file object on the model property.
                    });
                });

                scope.$watch(model, function (newValue, oldValue) {
                if (newValue === null || newValue === undefined || newValue === '') {
                    angular.element(element).val(''); // clears the file from the input element if the model is cleared.
                }
            });
        }
    };
});        

The AJAX call.

function saveFiles() {
            if (angular.isArray($scope.files) && $scope.files.length > 0) {
                var formdata = new FormData();

                for (var i = 0; i < $scope.files.length; i++) {
                    for (var key in $scope.files[i]) {
                        var value = $scope.files[i][key];    
                        formdata.append('[' + i + '].' + key, value);
                    }
                }

                var config = {
                    transformRequest: angular.identity,
                    headers: { 'Content-Type': undefined }                        
                };

                $http.post('/Area/Controller/SaveFiles', formdata, config)
                    .success(saveFilesCompleted);

                function saveFilesCompleted(data) {
                    // call back
                }
            }
        }
share|improve this answer
    
Could you please explain a little ? Where are you sending both the params ? Please explain the answer. Thanks . – StrugglingCoder Jun 23 at 10:25
    
Were you able to get it, in your case I think your model would be public class GroupMembershipModel { public int Id { get; set; } public string Name { get; set; } public List<HttpPostedFileBase> Files { get; set; } } try to send all of the data in the same formdata object, maybe you should append the files to formdata as an array. – Abdul Mateen Mohammed Jun 30 at 17:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.