1

I'm trying to upload a form with some text fields and a file to my WebAPI. Currently I always get a 415 error (a breakpoint in the ASP controller doesn't gets hit). My code looks like this:

Angular Service

// 'Upload' is from ng-file-upload
function applicationService(settings, $http, Upload) {
  var createCustomApplication = function(application) {
    var url = settings.baseUrl + '/api/applications/custom';

    var data = new FormData();
    angular.forEach(application, function (value, key) {
      data.append(key, value);
    });

    return Upload.upload({
      url: url,
      data: data,
      method: 'POST'
    });
  };

  return {
    createCustomApplication: createCustomApplication
  }
}

WebAPI controller

[ResponseType(typeof(ApplicationModel))]
[HttpPost, Route("api/applications/custom")]
public IHttpActionResult CreateCustomApplication([FromBody]ApplicationModel application)
{
   var file = HttpContext.Current.Request.Files[0];
   return Ok();
}

3 Answers 3

1

If you want to include a form with files as parameter to an action it is necessary to add a custom media formatter. Fortunately someone already created a Nuget-package for this. Configuration is easy. Install the package and add a line to your WebApiConfig-file.

This package allows you to use a HttpFile-object which captures your file either directly as a parameter or inside a model. From the docs:

[HttpPost]
public void PostFileBindRawFormData(MultipartDataMediaFormatter.Infrastructure.FormData formData)
{
    HttpFile file;
    formData.TryGetValue(<key>, out file);
}

or

public class PersonModel
{
    public string FirstName {get; set;}
    public string LastName {get; set;}
    public DateTime? BirthDate {get; set;}
    public HttpFile AvatarImage {get; set;}
    public List<HttpFile> Attachments {get; set;}
    public List<PersonModel> ConnectedPersons {get; set;}
}

//api controller example
[HttpPost]
public void PostPerson(PersonModel model)
{
    //do something with the model
}
Sign up to request clarification or add additional context in comments.

Comments

0

I've had the same issue. You should add the content type in your POST request.

headers: {
     'Content-Type': undefined
},

1 Comment

After adding the header I get the same error message. When I inspect my headers from my request in the devtools, nothing has changed (the header value is still multipart/form-data; boundary=----WebKitFormBoundaryVgMJf1g7g2DX9LUd)
0

You're code looks very similar to what I use. Perhaps the issue is to do with the multipart/form-data header value. I'm not experienced enough to say what is wrong in your implementation, but perhaps try this alternate async await approach.

[Route("api/applications/custom")]
[HttpPost]
public async Task<HttpResponseMessage> Upload()
{
    MultipartMemoryStreamProvider memoryStreamProvider;
    try
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
        }

        memoryStreamProvider = await Request.Content.ReadAsMultipartAsync();
    }
    catch (Exception e)
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest, string.Format("An error has occured while uploading your file. Error details: '{0}'", e.Message));    
    }

    // do something with your file...

    return Request.CreateResponse(HttpStatusCode.OK);

}

Here is my JS code. I also use promises instead of what ever is returned (if anything) from the Upload function.

$scope.submit = function() {
    if ($scope.form.file.$valid && $scope.file) {
        $scope.upload($scope.file);
    }
};

$scope.upload = function(file) {

    Upload.upload({
        url: 'api/applications/custom',
        data: { file: file }
    }).then(function(response) {
        // report the success to the user
    }, function(response) {
        // report the error to the user
    }, function(evt) {
        // report the progress of the upload to the user
        $scope.uploadProgress = evt.loaded / evt.total;
    });
};

I used the following article as a basis for my solution: http://monox.mono-software.com/blog/post/Mono/233/Async-upload-using-angular-file-upload-directive-and-net-WebAPI-service/

6 Comments

Doesn't work for me. The memoryStreamProvider is null.
Ah, but the WebAPI action is being hit now. That's more than you had before, right?
Yes, it seems when I remove the parameter the action gets hit.
I assume the additional "," in your upload object isn't causing the issue. Worth cleaning it up regardless. This one: method: 'POST',
Does your Upload actually return something? I use the promise notation to handle errors and successes. I'll post my js in my answer in case it gives you a clue.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.