Search code examples
asp.net-mvc-3windows-phone-7restuploadbackground-transfer

Uploading files with Windows Phone BackgroundTransfer service to an MVC3 site in a RESTful manner


I need my Windows Phone application to be able to upload audio files to my MVC3 site, using the BackgroundTransferService available in Mango.

As one possible solution, I can:

  1. Map a route to my controller:

    public override void RegisterArea(AreaRegistrationContext context)
            {
                context.MapRoute(
                    "SingleAudioFile",
                    "Api/Audio/Recieve",
                    new { controller = "AudioFiles", action = "Recieve" }
                    );
            }
    
  2. In the controller, have a Recieve action

    [HttpPost]    
    public JsonResult Recieve(byte[] audio)
         {
             // saving and status report logic here
         }
    

My question is: How do I set the system to bind file I upload from Windows Phone to a Recieve action's audio byte[] parameter?

On the phone, the data is being uploaded the following way:

BackgroundTransferRequest btr = new BackgroundTransferRequest (new Uri
                 (siteUrl + "Api/Audio/Recieve",UriKind.Absolute));
    btr.TransferPreferences = TransferPreferences.AllowBattery;
    btr.Method = "POST";
    btr.UploadLocation = new Uri("/" + Transfers + "/" + isoAudioFileName, UriKind.Relative);
Microsoft.Phone.BackgroundTransfer.BackgroundTransferService.Add(btr);

Solution

  • I am not quite sure what protocol does the BackgroundTransfer use to send the file but if it writes the buffer directly to the body of the POST request you could use a custom model binder to read directly from the request stream:

    public class BTModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            using (var ms = new MemoryStream())
            {
                controllerContext.HttpContext.Request.InputStream.CopyTo(ms);
                return ms.GetBuffer();
            }
        }
    }
    

    which could be registered like so:

    [HttpPost]
    public ActionResult Receive([ModelBinder(typeof(BTModelBinder))] byte[] audio)
    {
        ...
    }
    

    If it uses multipart/form-data then you could use a standard HttpPostedFileBase action parameter as shown here.