I found a few examples of web servers for MonoTouch but none of them parsed the data sent in a POST request. I looked around the web and was unable to find any examples of how to achieve this. So now that I’ve written it myself I’ve decided to share my own implementation. This includes not only the code for processing the form post data but also for registering request handlers etc.
Here is an example of how you would use the web server
1 public BookUploadViewController()
2 : base("BookUploadViewController", null)
3 {
4 RequestHandler = new DefaultRequestHandler();
5 var defaultActionHandlerFactory = new DefaultActionHandlerFactory();
6 RegisterActionHandlers(defaultActionHandlerFactory);
7 RequestHandler.AddActionHandlerFactory(defaultActionHandlerFactory);
8
9 WebServer = new EmbeddedWebServer(RequestHandler);
10 }
11
12 void RegisterActionHandlers(DefaultActionHandlerFactory factory)
13 {
14 factory.RegisterHandler(
15 request => request.RawUrl == "/",
16 request => new IndexActionHandler(request)
17 );
18 factory.RegisterHandler(
19 request =>
20 string.Compare(request.RawUrl, "/Upload", true) == 0 &&
21 string.Compare(request.HttpMethod, "POST", true) == 0,
22 request => new UploadActionHandler(request)
23 );
24 }
25
26 public override void ViewDidAppear(bool animated)
27 {
28 base.ViewDidAppear(animated);
29 StatusLabel.Text = string.Format("Server listening on\r\nhttp://{0}:8080", GetIPAddress ());
30 WebServer.Start(8080);
31 }
32
33 public override void ViewDidDisappear (bool animated)
34 {
35 base.ViewDidDisappear(animated);
36 WebServer.Stop();
37 }
38
And here are two app specific examples of request handlers
1 class IndexActionHandler : DefaultActionHandler
2 {
3 public IndexActionHandler(HttpListenerRequest request)
4 : base(request)
5 {
6 }
7
8 public override ActionResult Execute()
9 {
10 var result = new HtmlResult();
11 result.AppendLine("<html>");
12 result.AppendLine("<body>");
13 result.AppendLine("<h1>Upload an image</h1>");
14 result.AppendLine("<form action='/Upload' enctype='multipart/form-data' method='post'>");
15 result.AppendLine ("<input name='Image' type='file'/><br/>");
16 result.AppendLine("<input name='Upload' type='submit' text='Upload'/>");
17 result.AppendLine("</form>");
18 result.AppendLine("</body>");
19 result.AppendLine("</html>");
20 return result;
21 }
22 }
23
24 class UploadActionHandler : DefaultActionHandler
25 {
26 public UploadActionHandler(HttpListenerRequest request)
27 : base(request)
28 {
29 }
30
31 public override ActionResult Execute()
32 {
33 string errorMessage = null;
34 var file = FormData.GetFile("Image");
35 if (file == null
36 || file.FileData == null
37 || file.FileData.Length == 0
38 || string.IsNullOrEmpty(file.FileName))
39 errorMessage = "No image uploaded";
40
41 if (errorMessage == null)
42 ProcessFile(file);
43
44 var result = new HtmlResult();
45 result.AppendLine("<html>");
46 result.AppendLine("<body>");
47 if (errorMessage == null)
48 result.AppendLine("<h1>File uploaded successfully</h1>");
49 else
50 {
51 result.AppendLine("<h1>Error</h1>");
52 result.AppendLine("<h2>" + errorMessage + "</h2>");
53 }
54 result.AppendLine("</body>");
55 result.AppendLine("</html>");
56 return result;
57 }
58
59 void ProcessFile(MultiPartStreamFileValue postedFile)
60 {
61 string fileName = "Where to save the file";
62 using (var fileStream =
63 new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
64 {
65 fileStream.Write(postedFile.FileData, 0, postedFile.FileData.Length);
66 }
67 }
68
69 }
70
You can download the files here.