0

Trying to send some data & attachment(file) from AngularJS Client to MVC Web API and it does not work: I can see all the fields except of the attached file, which is shown as null

Here's the Model:

class Model{
 ... //the fields

public HttpPostedFileBase Photo { get; set; }//Attachment file, represented as an image
}

Here's the Web API:

public IHttpActionResult CreateModel([FromBody]Model model)
{
...
}

Here's the AngularJS code:

(function () {
angular.module("application")
       .controller("homeCtrl", ["$scope", "entityService",
           function ($scope, entityService) {

               $scope.createModel = function (model)
               {
                   entityService.createModel(model)
                                .then(function (data) {
                                    console.log(data);
                                });
               };

               $scope.model = {
                   FirstName: "John",
                   LastName: "Doe"                 
               };

           }]);
})();


"use strict";
(function () {
 angular.module("application")
       .factory("entityService", ["akFileUploaderService", function (akFileUploaderService) {
           var createModel = function (model) {
               return akFileUploaderService.saveModel(model, "/api/CreateModel");
           };
           return {
               createModel: createModel
           };
       }]);
})();


(function () {
"use strict"
angular.module("akFileUploader", [])
    .factory("akFileUploaderService", ["$q", "$http",
           function ($q, $http) {

               var saveModel = function (data, url) {
                   var deferred = $q.defer();

                   $http({
                       url: url,
                       method: "POST",
                       data: JSON.stringify(data),   
                       transformRequest: angular.identity,
                       headers: { 'Content-Type': "application/json" }  
                   }).success(function (result) {
                       deferred.resolve(result);
                   }).error(function (result, status) {
                       deferred.reject(status);
                   });
                   return deferred.promise;
               };

               return {
                   saveModel: saveModel
               }

           }])
    .directive("akFileModel", ["$parse",
            function ($parse) {
                return {
                    restrict: "A",
                    link: function (scope, element, attrs) {
                        var model = $parse(attrs.akFileModel);
                        var modelSetter = model.assign;
                        element.bind("change", function () {
                            scope.$apply(function () {
                                modelSetter(scope, element[0].files[0]);
                            });
                        });
                    }
                };
            }]);
})(window, document);

And here's HTML View:

....
<div class="form-group">
        <label for="attachment">Photo:</label>
        <div class="col-md-10">
            <input type="file" name="attachment" class="form-control" data-ak-file-model="model.Photo" />
        </div>
    </div>


    <button type="button" ng-disabled="newForm.$invalid" ng-click="createModel(model)" class="btn btn-primary">
        Create
    </button>
J.Doe
  • 33
  • 2
  • 8
  • @J.Doe..in your modal where you passing the Photo property? – MukulSharma Sep 09 '16 at 00:46
  • You need a CustomMEdiaTypeFormatter on the server side. See my answer here - http://stackoverflow.com/questions/38537484/post-image-to-asp-net-api-2-and-angular-2/38539120#38539120 . – Ravi A. Sep 09 '16 at 02:34
  • I don't think it's about a server side. The client side shows that json has nothing for a file although the object before conversion to json contains some data – J.Doe Sep 09 '16 at 08:02
  • @MukuiSharma: the Photo is a property of Model – J.Doe Sep 09 '16 at 08:03

1 Answers1

0

WebApi doesn't (currently) use the same mechanism as MVC with HttpPostedFileBase. See this question answer as an example to handling file uploads - a sample is below (simplified from the answer):

public async Task<HttpResponseMessage> AddFile()
{
    string root = HttpContext.Current.Server.MapPath("~/temp/uploads");
    var provider = new MultipartFormDataStreamProvider(root);
    var result = await Request.Content.ReadAsMultipartAsync(provider);

    foreach (var key in provider.FormData.AllKeys)
    {
        foreach (var val in provider.FormData.GetValues(key))
        {
            if (key == "aFormValue")
            {
                // do something with form data value
            }
        }
    }

    return this.Request.CreateResponse(HttpStatusCode.OK);
}

In a nutshell, you have to read the contents of the request picking out the file (and sometimes form) parts. You can use the built-in MultipartFormDataStreamProvider class and ReadAsMultipartAsync method on the HttpContent to do this.

The method above assumes you want to save to disk, when you want to put the file somewhere else it gets a little more tricky and you have to roll your own implementation of MultipartFormDataStreamProvider to handle this.

Community
  • 1
  • 1
Phil Cooper
  • 3,083
  • 39
  • 63