diff --git a/examples/c#/example.cs b/examples/c#/example.cs
new file mode 100644
index 0000000000000000000000000000000000000000..07f5048c01d30f5a6e8ce94da6351f909d5e6dd2
--- /dev/null
+++ b/examples/c#/example.cs
@@ -0,0 +1,27 @@
+// This file is part of mongoose web server project,
+// https://github.com/cesanta/mongoose
+
+using System;
+using System.Runtime.InteropServices;
+
+public class Program {
+  static private int RequestHandler(MongooseConnection conn) {
+    return 0;
+    /*
+    conn.write("HTTP/1.1 200 OK\r\n\r\n");
+    conn.write("Hello from C#!\n");
+    conn.write("Your user-agent is: " + conn.get_header("User-Agent") + "\n");
+    */
+  }
+
+  static void Main() {
+    Mongoose web_server = new Mongoose("c:\\", "8080",
+        new MongooseBeginRequest(RequestHandler));
+
+    Console.WriteLine("Mongoose v." + web_server.version_ + " started.");
+    Console.WriteLine("Press enter to exit program.");
+
+    // Serve requests until user presses "enter" on a keyboard
+    Console.ReadLine();
+  }
+}
diff --git a/examples/c#/mongoose.cs b/examples/c#/mongoose.cs
new file mode 100644
index 0000000000000000000000000000000000000000..68afed1f84d7f4ec4ed4fe6f143339d9f5a01e27
--- /dev/null
+++ b/examples/c#/mongoose.cs
@@ -0,0 +1,118 @@
+// This file is part of mongoose web server project,
+// https://github.com/cesanta/mongoose
+
+using System;
+using System.Runtime.InteropServices;
+
+[StructLayout(LayoutKind.Sequential)] public struct MongooseHeader {
+  public IntPtr name;    // Using IntPtr here because if we use strings here,
+  public IntPtr value;   // it won't be properly marshalled.
+};
+
+// mongoose.h :: struct mg_request_info
+[StructLayout(LayoutKind.Sequential)] public struct MongooseRequestInfo {
+  public string request_method;
+  public string uri;
+  public string http_version;
+  public string query_string;
+  public string remote_user;
+  public int remote_ip;
+  public int remote_port;
+  public int is_ssl;
+  public IntPtr user_data;
+  public IntPtr conn_data;
+  [MarshalAs(UnmanagedType.ByValArray,SizeConst=64)]
+    public MongooseHeader[] http_headers;
+};
+
+[UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate
+  int MongooseBeginRequest_native(IntPtr conn);
+public delegate int MongooseBeginRequest(MongooseConnection conn);
+
+// mongoose.h :: struct mg_callbacks
+[StructLayout(LayoutKind.Sequential)] public struct MongooseCallbacks {
+  public MongooseBeginRequest_native begin_request;
+  [MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
+    public IntPtr[] other_callbacks;
+};
+
+public class Mongoose {
+  public const string dll_name_ = "mongoose";
+  public string version_ = "??";
+
+  // These are here to store a ref to the callbacks
+  // while they are over in unmanaged code, to prevent garbage collection.
+  private event MongooseBeginRequest_native delegates;
+
+  private IntPtr ctx_;
+
+  [DllImport(dll_name_)] private static extern
+    IntPtr mg_start([MarshalAs(UnmanagedType.LPArray,
+                     ArraySubType=UnmanagedType.LPTStr)] string[] options,
+                    ref MongooseCallbacks callbacks,
+                    IntPtr user_data);
+  [DllImport(dll_name_)] public static extern
+    IntPtr mg_get_request_info(IntPtr conn);
+  [DllImport(dll_name_)] private static extern void mg_stop(IntPtr ctx);
+  [DllImport(dll_name_)] private static extern string mg_version();
+
+  public Mongoose(string document_root, string listening_ports,
+                  MongooseBeginRequest request_handler) {
+    version_ = mg_version();
+
+    string[] options = {
+      "document_root", document_root,
+      "listening_ports", listening_ports,
+      null
+    };
+
+    MongooseBeginRequest_native begin_request_cb = delegate(IntPtr conn) {
+      return request_handler(new MongooseConnection(conn, this));
+    };
+    MongooseCallbacks callbacks = new MongooseCallbacks();
+    callbacks.begin_request = begin_request_cb;
+
+    // Prevent garbage collection
+    delegates += begin_request_cb;
+
+    ctx_ = mg_start(options, ref callbacks, IntPtr.Zero);
+  }
+
+  ~Mongoose() {
+    if (this.ctx_ != IntPtr.Zero) {
+      mg_stop(this.ctx_);
+    }
+    this.ctx_ = IntPtr.Zero;
+  }
+}
+
+public class MongooseConnection {
+  public Mongoose mongoose;
+  private IntPtr conn;
+
+  [DllImport(Mongoose.dll_name_)] private static extern
+    string mg_get_header(IntPtr conn, string name);
+  [DllImport(Mongoose.dll_name_)] private static extern
+    string mg_get_var(IntPtr conn, string name);
+  [DllImport(Mongoose.dll_name_)] public static extern
+    int mg_write(IntPtr conn, string data, int length);
+
+  public MongooseConnection(IntPtr conn_, Mongoose mongoose_) {
+    mongoose = mongoose_;
+    conn = conn_;
+  }
+
+  public string get_header(string header_name) {
+    return mg_get_header(this.conn, header_name);
+  }
+
+  public string get_var(string header_name) {
+    string s = mg_get_var(this.conn, header_name);
+    string copy = "" + s;
+    return copy;
+  }
+
+  public int write(string data) {
+    return mg_write(this.conn, data, data.Length);
+  }
+}