Skip to content
Geovanni Perez edited this page May 27, 2016 · 24 revisions

How to receive a Multipart request

You can receive multipart request if you include this static method (from http://stackoverflow.com/questions/7460088/reading-file-input-from-a-multipart-form-data-post):

private static async Task ParseFiles(Stream data, string contentType, Action<string, Stream> fileProcessor)
        {
            var streamContent = new StreamContent(data);
            streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);

            var provider = await streamContent.ReadAsMultipartAsync();

            foreach (var httpContent in provider.Contents)
            {
                var fileName = httpContent.Headers.ContentDisposition.FileName;

                if (string.IsNullOrWhiteSpace(fileName))
                {
                    continue;
                }

                using (var fileContents = await httpContent.ReadAsStreamAsync())
                {
                    fileProcessor(fileName.Replace("\"", ""), fileContents);
                }
            }
        }

You need to include WebApi Client Nuget (https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Client).

Random Port selection demo (@waynebloss)

I just wanted to share with you a random port choosing demo that I created for myself. Perhaps you will want to build this feature into your project one day, but the example below is working fine for me and it may serve as a helpful example for other readers.

The wrapper class (StaticWebServer) is shown last. Here is how I now use it from my WinForms demo:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    using (var webServer = new StaticWebServer())
    {
        webServer.RunAsync();
        Application.Run(new Views.MainView(webServer.UsingBaseAddress));
    }
}

...and in the main view:

public MainView(string webViewUrl = "about:blank")
{
    InitializeComponent();
    browser.Url = new Uri(webViewUrl);
    mainStatusLabel.Text = "";
}

And finally, here is the StaticWebServer class, which chooses the port to use dynamically:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unosquare.Labs.EmbedIO;
using Unosquare.Labs.EmbedIO.Log;
using Unosquare.Labs.EmbedIO.Modules;

namespace YourOwnNamespace
{
    class StaticWebServer : IDisposable
    {
        public StaticWebServer() { }

        static Random _portGenerator = new Random();
        static List<int> _portsUsed = new List<int>();
        
        /// <summary>
        /// An instance of the (awesome!) EmbedIO WebServer.
        /// </summary>
        WebServer _server;

        /// <summary>
        /// String format template to merge the randomly generated port into.
        /// Default: "http://127.0.0.1:{0}/"
        /// </summary>
        public string BaseAddressTemplate { get; set; } = "http://127.0.0.1:{0}/";
        public int PortRangeMin { get; set; } = 51001;
        public int PortRangeMax { get; set; } = 65001;
        /// <summary>
        /// Relative or absolute path to serve static files from.
        /// </summary>
        public string RootFilesystemPath { get; set; } = "browse";

        /// <summary>
        /// The base address currently being used by the server.
        /// </summary>
        public string UsingBaseAddress { get; private set; }
        /// <summary>
        /// The port currently being used by the server.
        /// </summary>
        public int UsingPort { get; private set; }
        /// <summary>
        /// The root filesystem path currently being used by the server.
        /// </summary>
        public string UsingRootFilesystemPath { get; private set; }

        WebServer CreateServer(string baseAddress, string rootPath)
        {
            var logger = new DebugLogger();
            var server = new WebServer(baseAddress, logger);

            var headers = new Dictionary<string, string>()
            {
#if DEBUG
                // The following is mostly useful for debugging.
                { Constants.HeaderCacheControl, "no-cache, no-store, must-revalidate" },
                { Constants.HeaderPragma, "no-cache" },
                { Constants.HeaderExpires, "0" }
#endif
            };

            var staticFileMod = new StaticFilesModule(rootPath, headers);
            staticFileMod.DefaultExtension = ".html";
            server.RegisterModule(staticFileMod);

            return server;
        }

        string GetAbsoluteRootDirectoryPath()
        {
            if (Path.IsPathRooted(RootFilesystemPath))
                return RootFilesystemPath;
            var baseDir = Path.GetDirectoryName(
                System.Reflection.Assembly.GetEntryAssembly()
                .Location);
            return Path.Combine(baseDir, RootFilesystemPath);
        }

        public void RunAsync()
        {
            UsingRootFilesystemPath = GetAbsoluteRootDirectoryPath();
            Debug.Print("Serving static files from: {0}", UsingRootFilesystemPath);

            // Random port selection adapted from http://stackoverflow.com/a/223188/16387
            UsingPort = -1;
            UsingBaseAddress = null;
            while (true)
            {
                UsingPort = _portGenerator.Next(PortRangeMin, PortRangeMax);
                if (_portsUsed.Contains(UsingPort))
                    continue;

                UsingBaseAddress = String.Format(BaseAddressTemplate, UsingPort.ToString());
                _server = CreateServer(UsingBaseAddress, UsingRootFilesystemPath);
                try
                {
                    _server.RunAsync();
                } catch (System.Net.HttpListenerException)
                {
                    _server.Dispose();
                    _server = null;
                    continue;
                }
                _portsUsed.Add(UsingPort);
                break;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        void Dispose(bool disposing)
        {
            if (!disposing)
                return;

            var server = _server;
            _server = null;

            if (server == null)
                return;
            server.Dispose();
        }

        #region DebugLogger

        /// <summary>
        /// Provides a simple logger for Debug output.
        /// </summary>
        class DebugLogger : ILog
        {
            private static void WriteLine(string format, params object[] args)
            {
                var d = DateTime.Now;
                var dateTimeString = string.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}",
                    d.Year.ToString("0000"), d.Month.ToString("00"), d.Day.ToString("00"), d.Hour.ToString("00"),
                    d.Minute.ToString("00"), d.Second.ToString("00"), d.Millisecond.ToString("000"));

                format = dateTimeString + "\t" + format;
                
                if (args != null)
                    Debug.Print(format, args);
                else
                    Debug.Print(format);
            }
            
            public virtual void Info(object message)
            {
                InfoFormat(message.ToString(), null);
            }
            
            public virtual void Error(object message)
            {
                ErrorFormat(message.ToString(), null);
            }
            
            public virtual void Error(object message, Exception exception)
            {
                ErrorFormat(message.ToString(), null);
                ErrorFormat(exception.ToString(), null);
            }
            
            public virtual void InfoFormat(string format, params object[] args)
            {
                WriteLine(format, args);
            }
            
            public virtual void WarnFormat(string format, params object[] args)
            {
                WriteLine(format, args);
            }
            
            public virtual void ErrorFormat(string format, params object[] args)
            {
                WriteLine(format, args);
            }
            
            public virtual void DebugFormat(string format, params object[] args)
            {
                WriteLine(format, args);
            }
        }

        #endregion
    }
}
Clone this wiki locally