Monotouch Background authenticated Upload in IOS 7 and 8

213 Views Asked by At

I need to upload a file from my app to my ASP.NET WEB API backend. The HTTP POST request for the same is authenticated. Normally I do such Posts with HTTPWEBREQUEST class. And add token to request header as request.Headers.Set(HttpRequestHeader.Authorization,"Bearer "+ token); Now I need to do the same in a background Service as I don't want the user to wait with loading screen until transfer finishes. I am trying backgrounding in ios for the first time. Since I am targeting devices above IOS 7, I understood that I should be going for BackGround Transfer Service by implementing a NSUrlSession. I checked out the samples and found one to download a file with NSUrlSessionDownloadTask. It is similar to the way we download a file directly from it's URL using Webclient class. I also know that there is NSUrlSessionUploadTask for uploading files. But could not find an implementation in which I can POST my custom JSON which includes my upload file as byte array using NSUrlSessionUploadTask. I am only familiar with using HTTPWEBREQUEST and WEBCLIENT. Please provide me an example of how I can post my Custom Json in background with Headers for authentication.

This is what I have tried

I attempted to acheive this by refering to monotouch Downloading in background examples and obj-c NSMutableURLRequest POST examples.

var jsonstr = JsonConvert.SerializeObject(imgvm);
byte[] bytes = Encoding.UTF8.GetBytes(jsonstr);
NSUrlSession session = null;
NSUrlSessionConfiguration configuration = NSUrlSessionConfiguration.BackgroundSessionConfiguration ("com.KeepCard.BackgroundSession"); 
session = NSUrlSession.FromConfiguration (configuration, (NSUrlSessionDelegate) new MySessionDelegate(), new NSOperationQueue());
const string UploadURLString = "**************";
NSUrlSessionUploadTask uploadTask;

NSUrl uploadURL = NSUrl.FromString (UploadURLString);
NSMutableUrlRequest requests = new NSMutableUrlRequest (uploadURL);
requests.HttpMethod="POST";
NSData bodyData = NSData.FromArray(bytes);
Dictionary<string,string> nsmd = new Dictionary<string, string> ();
nsmd.Add("Content-Type","application/json");
nsmd.Add("Content-Length",bytes.Length.ToString());
nsmd.Add("Authorization","Bearer "+token);
//  nsmd.Add("Accept","*/*");

foreach (var header in nsmd) 
{
    requests[header.Key] = header.Value;
}
uploadTask = session.CreateUploadTask (requests);

imgvm is the viewmodel and jsonstr is the JsonString to be Posted. This is my NSUrlSessionTaskDelegate

public class MySessionDelegate : NSUrlSessionTaskDelegate
{
    public override void DidFinishEventsForBackgroundSession (NSUrlSession session)
    {
        var appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;

        // Handle new information, update UI, etc.

        // call completion handler when you're done
        if (appDelegate.backgroundSessionCompletionHandler != null) {
            NSAction handler = appDelegate.backgroundSessionCompletionHandler;
            appDelegate.backgroundSessionCompletionHandler = null;
            handler.Invoke ();
        }
    }
    public override void DidReceiveChallenge (NSUrlSession session, NSUrlAuthenticationChallenge challenge, Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
    {
        Console.WriteLine ("Check Here");
    }
    public override void DidReceiveChallenge (NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
    {
        Console.WriteLine ("Check Here");

    }
    public override void DidBecomeInvalid (NSUrlSession session, NSError error)
    {
        Console.WriteLine ("Check Here");
    }
    public override void DidCompleteWithError (NSUrlSession session, NSUrlSessionTask task, NSError error)
    {
        Console.WriteLine ("Check Here");
    }

}

Also I have these in my AppDelegate

public override void HandleEventsForBackgroundUrl (UIApplication application, string sessionIdentifier, NSAction completionHandler)
{
    this.backgroundSessionCompletionHandler = completionHandler;
}

Please point out to me what am I doing wrong. Do I have to enable background mode in info.plist ? I did not enable because none of the modes specified matched "Background Transfer Service. When I run now the execution comes upto session.CreateUploadTask (requests); and then the app stops without any exception

0

There are 0 best solutions below