A Dutch software developer living in Chile
# Monday, July 27, 2009
A very simple GZip command line tool

During some testing, I needed a tool that could simply compress a file to GZip format and back again. I decided that other people might have a similar need, so here’s the code to make it work.

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Compression;
using System.IO;

namespace GZip
{
  class Program
  {
    static void Main(string[] args)
    {
      CompressionMode mode = CompressionMode.Compress;

      if (args.Length != 3)
      {
        ShowUsage();
        return;
      }

      string command = args[0].ToLower();
      switch (command)
      {
        case "compress":
          mode = CompressionMode.Compress;
          break;
        case "decompress":
          mode = CompressionMode.Decompress;
          break;
        default:
          ShowUsage();
          return;
      }

      Stream sourceStream = File.OpenRead(args[1]);
      Stream targetStream = File.OpenWrite(args[2]);

      switch (mode)
      {
        case CompressionMode.Compress:
          using (GZipStream gZip = new GZipStream(targetStream, CompressionMode.Compress))
          {
            Pump(sourceStream, gZip);
          }

          break;
        case CompressionMode.Decompress:
          using (GZipStream gZip = new GZipStream(sourceStream, CompressionMode.Decompress))
          {
            Pump(gZip, targetStream);
          }
          break;
      }
      sourceStream.Close();
      targetStream.Close();

    }

    private static void Pump(Stream source, Stream target)
    {
      byte[] buffer = new byte[65536];
      int count;
      while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
      {
        target.Write(buffer, 0, count);
      }

    }

    private static void ShowUsage()
    {
      Console.WriteLine("Usage: GZip compress | decompress   sourceFileName targetFileName");
    }
  }
}


Monday, July 27, 2009 3:02:34 PM (Pacific SA Standard Time, UTC-04:00)  #    Comments [0]  Programming

World’s smallest web server

It’s always fun to play with .Net, the HTTP Listener class in .Net 2.0 makes it really easy. With this little block of code you can setup a very simple (multithreaded) web server…

private static System.Threading.AutoResetEvent listenForNextRequest = new System.Threading.AutoResetEvent(false);

protected Server() 
{
  _httpListener = new HttpListener();
}

private HttpListener _httpListener;

public string Prefix { get; set; }
public void Start()
{
  if (String.IsNullOrEmpty(Prefix))
    throw new InvalidOperationException("No prefix has been specified");
  _httpListener.Prefixes.Clear();
  _httpListener.Prefixes.Add(Prefix);
  _httpListener.Start();
  System.Threading.ThreadPool.QueueUserWorkItem(Listen);

}

internal void Stop()
{
  _httpListener.Stop();
  IsRunning = false;
}

public bool IsRunning { get; private set; }

private void ListenerCallback(IAsyncResult result)
{
  HttpListener listener = result.AsyncState as HttpListener;
  HttpListenerContext context = null;

  if (listener == null)
    // Nevermind
    return;

  try
  {
    context = listener.EndGetContext(result);
  }
  catch (Exception ex)
  {
    System.Diagnostics.Debug.WriteLine(ex.ToString());
    return;
  }
  finally
  {
    listenForNextRequest.Set();
  }
  if (context == null)
    return;
  ProcessRequest(context);
}

// Loop here to begin processing of new requests.
private void Listen(object state)
{
  while (_httpListener.IsListening)
  {
    _httpListener.BeginGetContext(new AsyncCallback(ListenerCallback), _httpListener);
    listenForNextRequest.WaitOne();
  }
}

protected abstract void ProcessRequest(HttpListenerContext context);

Always nice to have ;)


Monday, July 27, 2009 1:21:45 PM (Pacific SA Standard Time, UTC-04:00)  #    Comments [0]  Programming

# Sunday, June 07, 2009
Running code in a different AppDomain

Let’s say you would like to be able to extend your application with C# scripting abilities. You can do this by simply compiling the script and running it. The problem is that these kind of scripts take up memory that isn’t going to be released any time soon. Another problem is that the script can do anything your program can… or when an exception is thrown, your program crashes… is that really the idea?

Enter the use of application domains. Application domains are just for doing these kind of things. Loading temporary assemblies, executing partially trusted code and do memory-intensive work so you don’t need to GC.Collect at the end of the day. (Normally we wouldn’t want to interfere with .Net memory management, because there wouldn’t be much reason to. .Net does a very good job all by itself!)

Let’s start with a very simple example:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace MyAppDomain
{
  class Program
  {
    static void Main(string[] args)
    {
      Worker localWorker = new Worker();
      Console.WriteLine("localWorker is running in: {0}", localWorker.DomainName);
      AppDomain myDomain = null;
      try
      {
        myDomain = AppDomain.CreateDomain("Remote Domain");
        Worker remoteWorker = (Worker)myDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "MyAppDomain.Worker");
        Console.WriteLine("remoteWorker is running in: {0}", remoteWorker.DomainName);
      }
      finally
      {
        if (myDomain != null) 
          AppDomain.Unload(myDomain);
      }

    }
  }

  public class Worker : MarshalByRefObject
  {
    public Worker()
    {

    }

    public string DomainName
    {
      get
      {
        return AppDomain.CurrentDomain.FriendlyName;
      }
    }

  }
}

What you see here is:

  • An application domain is created
  • A value is sent from the new application domain back to the local domain.
  • We have a strongly-typed reference to the remote object

In this example, the remote domain is running with the same privileges as the local domain.

Let’s crash…

Unhandled exceptions can cause code to crash or leave your application in an unstable state. AppDomains are isolated and can help you to catch unhandled exceptions and unload the application domain when needed. So when we expand our example to include this, we get something like this:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace MyAppDomain
{
  class Program
  {
    static void Main(string[] args)
    {
      AppDomain myDomain = null;
      try
      {
        myDomain = AppDomain.CreateDomain("Remote Domain");
        myDomain.UnhandledException += new UnhandledExceptionEventHandler(myDomain_UnhandledException);
        Worker remoteWorker = (Worker)myDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Worker).FullName);
        remoteWorker.VeryBadMethod();
      }
      catch(Exception ex)
      {
        myDomain_UnhandledException(myDomain, new UnhandledExceptionEventArgs(ex, false));
      }
      finally
      {
        if (myDomain != null)
          AppDomain.Unload(myDomain);
      }

      Console.ReadLine();
    }

    static void myDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
      Exception ex = e.ExceptionObject as Exception;
      if (ex != null)
        Console.WriteLine(ex.Message);
      else
        Console.WriteLine("A unknown exception was thrown");
    }
  }

  public class Worker : MarshalByRefObject
  {
    public Worker()
    {

    }

    public string DomainName
    {
      get
      {
        return AppDomain.CurrentDomain.FriendlyName;
      }
    }

    public void VeryBadMethod()
    {
      // Autch!
      throw new InvalidOperationException();
    }

  }
}

Loading assemblies in the remote application domain

When loading an assembly in the remote domain, the assembly gets unloaded once the application domain gets unloaded. So if Worker would load an assembly, this would not be a problem as long as worker is in a separate domain. Here’s another example.

First, we create a simply plugin assembly:

using System;
using System.Collections.Generic;
using System.Text;

namespace MyPluginAssembly
{
  public class MyPlugin
  {
    public MyPlugin()
    {

    }

    public string Hello()
    {
      return "Hello";
    }
  }
}

This assembly needs to be compiled and for the sake of simplicity we’ll call it “MyPluginAssembly.dll”. Copy this dll to the same directory as the MyAppDomain output folder. Next, we’ll change the example a bit and load the assembly, do some reflection, run the Hello method and print the result.

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace MyAppDomain
{
  class Program
  {
    static void Main(string[] args)
    {
      AppDomain myDomain = null;
      try
      {
        myDomain = AppDomain.CreateDomain("Remote Domain");
        myDomain.UnhandledException += new UnhandledExceptionEventHandler(myDomain_UnhandledException);
        Worker remoteWorker = (Worker)myDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Worker).FullName);

        Console.WriteLine(remoteWorker.RunPlugin());

        PrintAssemblies(myDomain);
        PrintAssemblies(AppDomain.CurrentDomain);

      }
      catch(Exception ex)
      {
        myDomain_UnhandledException(myDomain, new UnhandledExceptionEventArgs(ex, false));
      }
      finally
      {
        if (myDomain != null)
        {
          Console.ForegroundColor = ConsoleColor.Red;
          Console.WriteLine("Unloading {0}", myDomain.FriendlyName);
          Console.ForegroundColor = ConsoleColor.Gray;
          AppDomain.Unload(myDomain);
        }
      }

      PrintAssemblies(AppDomain.CurrentDomain);


      Console.ReadLine();
    }

    static void myDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
      Exception ex = e.ExceptionObject as Exception;
      if (ex != null)
        Console.WriteLine(ex.Message);
      else
        Console.WriteLine("A unknown exception was thrown");
    }

    static void PrintAssemblies(AppDomain domain)
    {
      Console.ForegroundColor = ConsoleColor.Yellow;
      Console.WriteLine("Assemblies loaded in domain {0} are:", domain.FriendlyName);
      Console.ForegroundColor = ConsoleColor.Gray;
      foreach (var item in domain.GetAssemblies())
      {
        Console.WriteLine(item.FullName);
      }
    }
  }



  public class Worker : MarshalByRefObject
  {
    public Worker()
    {

    }

    public string DomainName
    {
      get
      {
        return AppDomain.CurrentDomain.FriendlyName;
      }
    }

    public string RunPlugin()
    {
      Assembly asm = Assembly.LoadFrom("MyPluginAssembly.dll");
      Type pluginType = asm.GetType("MyPluginAssembly.MyPlugin");
      object plugin = pluginType.GetConstructor(new Type[0]).Invoke(new object[0]);
      return (string)pluginType.GetMethod("Hello").Invoke(plugin, new object[0]);
    }

  }
}

What you’ll notice is that the first list will show that the remote’s plugin assembly is also loaded in the local appdomain. But once the AppDomain is unloaded, the plugin assembly is gone.
Sunday, June 07, 2009 12:43:50 PM (Pacific SA Standard Time, UTC-04:00)  #    Comments [0]  Programming

# Friday, June 05, 2009
Adding some UI elements with jQuery to an MVC app

One of the requirements that I have on an application that I’m working on is that the user can select a date easily when a textbox has focus. I wanted this to do in such a manner that programmatically this can be done with minimum effort, and that a few extra things are taken into account:

  • Nullable dates (i.e. end dates) should be allowed with an empty text box
  • Not-nullable dates should default to the date of today
  • Multiple date pickers should be possible within the same form

Ingredients

For this to work out, I’ve used the date picker control that’s available at http://jqueryui.com/ Besides that, I’m using ASP.Net MVC 1.0

Creating an extension method for System.Web.Mvc.ViewUserControl

For the view, I’m using an extension method that’s called “DateField”. This allows me to use the date field without having to use things like “RenderPartial” and creating custom models.

This class looks like this:

public static class ViewUserControlDateFieldExtension
{
  public static string DateField(this IViewDataContainer control, string fieldName)
  {
    return DateField(control, fieldName, control.ViewData.Eval(fieldName) as DateTime?, false);
  }

  public static string DateField(this IViewDataContainer control, string fieldName, bool allowNulls)
  {
    return DateField(control, fieldName, control.ViewData.Eval(fieldName) as DateTime?, allowNulls);
  }

  public static string DateField(this IViewDataContainer control, string fieldName, DateTime? value)
  {
    return DateField(control, fieldName, value, false);
  }

  public static string DateField(this IViewDataContainer control, string fieldName, DateTime? value, bool allowNulls)
  {
    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("<input type=\"text\" name=\"{0}\" value=\"{1}\" class=\"datepicker\" />", fieldName, GetFieldValue(control, value, allowNulls));
    return sb.ToString();
  }

  private static string GetFieldValue(IViewDataContainer control, DateTime? value, bool allowNulls)
  {
    if (allowNulls)
    {
      if (value.HasValue)
        return value.Value.ToString("dd-MM-yyyy");
      else
        return String.Empty;
    }
    else
    {
      if (value.HasValue)
      {
        if (value.Value == DateTime.MinValue)
          return DateTime.Now.ToString("dd-MM-yyyy");
        else
          return value.Value.ToString("dd-MM-yyyy");
      }
      else
        return DateTime.Now.ToString("dd-MM-yyyy");
    }
  }
}

Next, adding some jQuery script

Adding the script to the master page is easy. Just a few <script> tags and that’s it.

<link href="/themes/redmond/ui.all.css" type="text/css" rel="Stylesheet" />
<script src="/Scripts/jquery-1.3.2.js" type="text/javascript"></script>
<script src="/Scripts/ui/ui.core.js" type="text/javascript"></script>
<script src="/Scripts/ui/ui.datepicker.js" type="text/javascript"></script>
<script src="/Scripts/ui/i18n/ui.datepicker-nl.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
  // Configure and add a date picker.
  $(function() {
  $(".datepicker").datepicker({
    changeMonth: true,
    changeYear: true
  });
  $(".datepicker").datepicker('option', { dateFormat: 'dd-mm-yy' });
  $.datepicker.setDefaults($.extend({ showMonthAfterYear: false }, $.datepicker.regional['nl']))
});
</script>

Finally, use the class

Using the class is as easy as using this little line of code for a date field:

<% = this.DateField("EndDate", true) %>

The result looks like this:

image

The most nice part? It works in IE7, IE8, Opera, Chrome, FireFox and Safari.

UPDATE: Why use IViewDataContainer

I had a question from someone who wanted to know why I choose to extend IViewDataContainer in stead of WebControl/WebPage. The reason is simple. Both the System.Web.Mvc.ViewPage en System.Web.Mvc.ViewControl implement IViewDataContainer. This makes the interface the easiest target to implement.


Friday, June 05, 2009 5:03:17 PM (Pacific SA Standard Time, UTC-04:00)  #    Comments [0]  MVC | Programming

# Monday, May 25, 2009
Oh dear, another language makes it into .Net

Microsoft will release a new programming language… er, 2 new programming languages with .Net 4.0. One is called “F#”, the other one “M”.

F# is a functional programming language that made it’s appearance around the end of 2004, but became more popular in the last year. Now, F# is so successful it will make it into .Net 4.0 and Visual Studio 2010. 

The other language is ”M” which allows a developer to model the solution in to basic blocks and verify that the code actually conforms to the model.

Both languages will mean a new steep learning curve for all those who are interested, but that’s what developers do: we learn new things as we go along. A developer who doesn’t learn can go and retire in about 5 years from now.

I’ve got the Visual Studio 2010 beta running, and I’ll be playing a bit with all this :)

image


Monday, May 25, 2009 10:23:00 AM (Pacific SA Standard Time, UTC-04:00)  #    Comments [0]  Programming | Visual Studio 2010