Calling a .NET web service endpoint with NSURLSessionUploadTask
I have been going through the process of removing open source components from my apps when Cocoa Touch and the associated frameworks catch up with what I need to do.
Let’s say for the sake of argument you have a .NET web service that looks like this:
using System; using System.Web.Script.Services; using System.Web.Services; namespace My_WebRole { /// <summary> /// Summary description for CreateCustomer /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] [ScriptService] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class CreateCustomer : WebService { [WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json)] public string Create() { try { var myName = Context.Request.Form["MyName"]; var companyName = Context.Request.Form["CompanyName"]; var db = new MyServicesDataContext(); var row = new CustomerInformation { MyName = myName, CompanyName = companyName, CreationDate = DateTime.Now }; db.CustomerInformations.InsertOnSubmit(row); db.SubmitChanges(); } catch (Exception ex) { return ex.ToString(); } return "OK"; } } } |
The NSURLSessionUploadTask class was added in iOS 7, which is sufficiently long enough ago to be stable to implement. (As long as your app is going to require iOS 7 or newer, of course.)
Here is what the code looks like that calls the above web service:
+ (BOOL)pushTheData:(NSString *)myName companyName:(NSString *)companyName { NSMutableString *urlString = [NSMutableString stringWithString:PUSH_DATA_URL]; NSString *boundary = [NSString boundaryString]; NSMutableData *body = [NSMutableData data]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", @"MyName"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"%@\r\n", myName] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", @"CompanyName"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"%@\r\n", companyName] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; configuration.HTTPAdditionalHeaders = @ { @"Content-Type" : [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] }; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration]; NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { // handle the error return; } NSLog(@"Response: %@", [data utf8String]); // do something here }]; [task resume]; return YES; } |
The above method uses a category that I have set up off of NSString that creates a new boundary string each time it is called. Here is that method:
+ (NSString *)boundaryString { NSString *uuidStr = [[NSUUID UUID] UUIDString]; return [NSString stringWithFormat:@"Boundary-%@", uuidStr]; } |
BTW, Happy Birthday to Jeff Beck. He has a new album coming out soon, and I can’t wait to hear it.