January 25, 2010

Load a dll into an AppDomain for reflection or execution and Unload it

.Net will allow you to easily load any dll you want to into the current AppDomain by simply calling Assembly.LoadFrom() with the path of the dll in question. However, this is only available for the current AppDomain, and as a result, the dll remains loaded for the duration of the AppDomain's lifetime.

This may be ok, but if you want to simply load a dll, inspect it, and run some one-time operations on it, that seems a bit wasteful. In web development, it means you must shut down your web server to recompile the dll you're loading.

So, the solution would seem to be to start up a new appDomain, load the dll in question, do your work, and then unload the appDomain.

Gentlemen, start your compilers...

namespace Utilities {
  public class SomeClass{
    public static void RegisterApplication(
      string appPath) {
      if (File.Exists(appPath)) {
        var domainSetup = new AppDomainSetup() {
        ApplicationBase = AppDomain.CurrentDomain
          .BaseDirectory,
        PrivateBinPath = AppDomain.CurrentDomain
          .BaseDirectory + @"\bin"
      };
      var appDomain = AppDomain.CreateDomain(
        "LoaderDomain", null, domainSetup);
      try {
        var loader = (Loader)appDomain
          .CreateInstanceAndUnwrap(
            Assembly.GetExecutingAssembly()
              .FullName,
            typeof(Loader).FullName);
        loader.DoSomething(appPath);
      }
      finally { AppDomain.Unload(appDomain); }
    }
  }

  public class Loader: MarshalByRefObject {
    public void DoSomething(string appPath) {
      var assembly = Assembly.LoadFrom(appPath);
      foreach (var type in assembly.GetTypes()){
      // Do something with the types we find
      // like create some classes with known 
      // interfaces or examine attributes
      }
    }
  }
}

What's going on?

Well, we create an app domain and seed the PrivateBinPath with a \bin subdirectory so that we can load our current dll in an IIS or cassini environment. Then we fire off the known object and have it call into Assembly.LoadFrom(). Assembly.LoadFrom will resolve dependencies using the standard resolution stuff for our other assemblies. Alternately, we could use a custom resolver event handler to get to our dlls.

January 18, 2010

CSRF (Cross-Site Request Forgery) Handling in MVC

Phil Haack's talk on asp.net reminded me of the importance of handling CSRF attacks. In MVC, this is simply handled with a one-two punch. In your posting form, you need to include the Html.AntiForgeryToken() in the form as follows:

  

The other thing is to add an [ValidateAntiForgeryToken] attribute to the targeted posting action in your controller as follows:
[ValidateAntiForgeryToken]
[HttpPost] 
// or MVC 1.0 style [AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Delete(FormCollection form, int id) {
  // code here to delete stuff
  return View();
}
Also don't forget that we want to make sure that any state-changing operations are always posts!
My new syntax highlighting is accomplished via a method outlined on Carter Cole's most excellent blog.