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 description for CreateCustomer
///
[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.