2

I have a webapi project and cannot figure out a nice way to bind the uploaded file content.

I have an entity framework model as follows:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public UploadedFileId UploadedFileId { get; set; }
    public virtual UploadedFile UploadedFile { get; set; }
}

Where uploaded file is as follows:

public class UploadedFile
{
    public int Id { get; set; }
    public byte[] Content { get; set; }
    public string FileName { get; set; }
}

I have a SPA on the client with the form uploading the file,

In the controller I try get the model binding working with the file upload, but neither of my try works.

Version 1:

using System.Web.Http;

...

public IHttpActionResult Post(Person entity) {
    /* some code */
}

This is obviously not working, although the model itself is null, which I do not understand why. I was expecting it will bind the properties and just ignoring the file.

Version 2:

public IHttpActionResult Post(Person entity, HttpPostedFileBase somefile) {
    /* some code */
}

Also tried with different name in the form input on client side (file, fileUpload, files, HttpPostedFile, HttpPostedFileBase)

Version 3:

public IHttpActionResult Post(HttpPostedFileBase somefile) {
    /* some code */
}

somefile is null here as well.

Version 4: Tried to create a binding

public class UploadedFilesModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        HttpPostedFileBase file =controllerContext.HttpContext.Request.Files[bindingContext.ModelName];
        var uploadFile = new UploadedFile();
        uploadFile.FileName = file.FileName;
        uploadFile.Content = new byte[(int)file.InputStream.Length];
        file.InputStream.Read(uploadFile.Content, 0, (int)file.InputStream.Length);

        return uploadFile;
   }
}

Global.asax

ModelBinders.Binders[typeof(UploadedFile)] = new UploadedFilesModelBinder();

Controller

public IHttpActionResult Post(UploadedFile somefile) {
    /* some code */
}

Custom binder never called.


I could access the files from the context request form, but the model are quite complex and that would mean I have to bind its properties myself. I do not want to write a binder if there is already one in the framework. Is there a way of solving this issue?

lyttlegy
  • 101
  • 5

1 Answers1

0

Have a look at this answer https://stackoverflow.com/a/19746825/2138959. Also based on Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME you could read multipart form data. First part that will represent the model you can map to model with media type formatter to avoid manual properties mapping and then read second part with the file and set the file manually to the model.

Community
  • 1
  • 1
Andrii Litvinov
  • 12,402
  • 3
  • 52
  • 59