random .NET and web development musings

The objectives for this post are to outline how to:

  • Create a user account in AD
  • Create a folder to hold the website code and assign the user read/execute rights
  • Grant the user access to use ASP.NET
  • Create an app pool running as our new identity
  • Create an iis site assigned to the app pool and pointing at our folder

First off you will need to add a reference to Microsoft.web.Administration.dll, which is in

c:\windows\system32\InetSrv

These are the namespaces you’ll need:

using System;
using System.Diagnostics;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Security.AccessControl;
using Microsoft.Web.Administration;

To begin we need to get a handle on AD, specifically the container where we want our user to be created:

var usersContext = new PrincipalContext(ContextType.Domain, "MyDomain", "ou=Users,ou=MyDomain,dc=MyDomain");

Next we create the user:

var webUser = new UserPrincipal(usersContext, "username", "password", true);
webUser.Save();

We then need to grant access to ASP.NET for the user (perhaps with v2 instead of v4)

Process.Start(@"c:\windows\microsoft.net\framework64\v4.0.30319\aspnet_regiis.exe", "-ga username");

Next we create the directory where we want the code to be housed, and grant the user read and execute permission on the folder:

var deploymentDir = Directory.CreateDirectory(fullPath);
var deploymentDirSecurity = deploymentDir.GetAccessControl();

deploymentDirSecurity.AddAccessRule(new FileSystemAccessRule("MyDomain\" + webUser.Name, FileSystemRights.ReadAndExecute, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));

deploymentDir.SetAccessControl(deploymentDirSecurity);

Now we can create the app pool:

var manager = new ServerManager();

var applicationPool = manager.ApplicationPools.Add("My new app pool");

applicationPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
applicationPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
applicationPool.ProcessModel.UserName = parameters.Username;
applicationPool.ProcessModel.Password = parameters.Password;

And then the site:

var site = manager.Sites.Add("My new IIS site", "http", ":80:mydomain.com", fullPath);
site.Applications[0].ApplicationPoolName = "My new app pool";

manager.CommitChanges();

And there you have it :)

I’ve already got a bunch of lovely build scripts and remote management scripts that I won’t go into here, what I am going to talk about is how I’ve wired them together using MSDeploy to push my code to my remote server.

First off, install the Web Deployment Tool on your remote machine, but to help prevent haxing don’t put the remote agent service on the default URI. Instead I used a custom port and set up a firewall rule to only allow this port from our office’s IP address. Download the installer and run:

    msiexec /I WebDeploy_x64_en-US.msi /passive ADDLOCAL=ALL LISTENURL=http://+:1234/MSDeploy/

N.B. you can change the port and path to whatever you like.

Here are the installation docs.

Next, goto Services and start “Web Deployment Agent Service”, or run:

    net start msdepsvc

You probably also want to set it to Automatic instead of Manual. Then, set up your MSDeploy script to push your code:

    c:\program files\iis\microsoft web deploy\msdeploy.exe -verb:sync
        -source:dirPath='d:\some\local\path'
        -dest:dirPath='f:\some\remote\path',computerName=http://xxx.xxx.xxx.xxx:1234/MSDeploy,
            userName=remoteUser,password=remotePassword -verbose

N.B. “dirPath” is for pushing a whole directory, you can’t use this for a single file (I’m sure there’s a different switch for that though, see the docs, good luck.)

You can then execute a remote command:

    c:\program files\iis\microsoft web deploy\msdeploy.exe -verb:sync
        -source:runCommand='f:\some\remote\path\somefile.bat',waitInterval=15000,waitAttempts=1
        -dest:auto',computerName=http://xxx.xxx.xxx.xxx:1234/MSDeploy,
            userName=remoteUser,password=remotePassword -verbose

The docs say that “waitAttempts” is the number of subsequent retry attempts so initially set it to 0, but I found that any waitInterval causes a timeout unless I set “waitAttempts” to 1 (presumably anything >0). Crap, but it works.

Note that in this example runCommand will call:

    "C:\Windows\System32\cmd.exe" /c "f:\some\remote\path\somefile.bat"

which means the current directory for the execution of the batch file is “C:\Windows\System32″. If you put:

    cd /d %~dp0

in your batch file, it will change the working dir to the path where the batch file resides. 1337.

Here are some docs.

MSDemply runCommand docs
MSDeploy Command line docs
MSDeploy Command line docs part deux (the bit you actually need)

Here is a simple jQuery plugin to allow users to filter table rows through dropdowns in the header rows.

Read more…

It seems IE doesn’t print canvas elements which are absolutely positioned in the correct place. What a surprise.

This problem came about when i tried to print some of my jqPlot graphs, as it uses absolutely positioned canvas tags for the data and axes.

There’s probably a much easier solution to this, but i couldn’t find it.

Heres some mega-hax that makes things work:

Update: This requires jQuery 1.4.2+

(function($) {
	$.fn.CanvasHack = function() {
		var canvases = this.find('canvas').filter(function() {
			return $(this).css('position') == 'absolute';
		});

		canvases.wrap(function() {
			var canvas = $(this);
			var div = $('<div />').css({
				position: 'absolute',
				top: canvas.css('top'),
				left: canvas.css('left')
			});
			canvas.css({
				top: '0',
				left: '0'
			});
			return div;
		});

		return this;
	};
})(jQuery);

Call it after your graph setup code, like this:

$('body').CanvasHack();

Quick Link: Download the Example Code.

OK so here’s my problem,

My client wants most of the actions in their system to work slightly differently based on the authorization role of the logged in user. For example, Moderators can edit a user, but only some fields, Administrators can edit all fields for a user.

I don’t want to have different URIs for each action, I don’t want to have to faff about with routes, I want to do this transparently, with as little pain as possible.

One approach would be to have a switch inside the method (on the current users role) and delegate the action to the private method specific to that role. However this suffers several problems:

The main action method that gets called by the controller can only have a single Resource type, which means if you want different resource types per role, youre in a mess. You therefore have to accept FormCollection, then do binding and validation manually etc. etc. urgh. You also end up with 4 methods for each action. This quickly bloats your controller :(

So, what can we do about this? We’ll in this post I’ll show you how you can leverage the power of you IoC container to swap out the controller instance with one specific to the current user’s role.

Here’s what you do:

Create an IXXXController for each of your controllers you want to swap based on role, like this:

public interface IUserController : IController
{
	ActionResult Edit(int id);
}

Then, create your multiple implementations of this controller:

public class UserController_ForAdministrator : Controller, IUserController
{
	[AcceptVerbs(HttpVerbs.Get)]
	public override ActionResult Edit(int id)
	{
		// this would really come from a repos
		var resource = new EditUser_AdministratorResource{ EmailAddress = "me@here.com"};

		return View("Edit_Administrator", resource);
	}

	[AcceptVerbs(HttpVerbs.Post)]
	public ActionResult Edit(int id, EditUser_AdministratorResource resource)
	{
		// do admin stuff here

		return RedirectToAction("Index");
	}
}

public class UserController_ForModerator : HomeController
{
	[AcceptVerbs(HttpVerbs.Get)]
	public override ActionResult Edit(int id)
	{
		// this would really come from a repos
		var resource = new EditUser_ModeratorResource{ EmailAddress = "me@here.com"};

		return View("Edit_Moderator", resource);
	}

	[AcceptVerbs(HttpVerbs.Post)]
	public ActionResult Edit(int id, EditUser_ModeratorResource resource)
	{
		// save moderator stuff here

		return RedirectToAction("Index");
	}
}

Next, you need a custom IControllerFactory. Note in the example below I have forgone any error checking or optimisation for brevity, I have also omitted any Namespace checking.

public class CustomControllerFactory : IControllerFactory
{
	private readonly IEnumerable<Type> controllerTypes;

	public CustomControllerFactory()
	{
		this.controllerTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => (t.IsInterface || !t.IsAbstract) && t.Name.EndsWith("Controller"));
	}

	public IController CreateController(RequestContext requestContext, string controllerName)
	{
		var currentUser = ObjectFactory.GetInstance<User>();

		var controllerInterface = this.controllerTypes.Where(t => t.IsInterface && t.Name.Equals("I" + controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
		if (controllerInterface != null)
		{
			return ObjectFactory.GetNamedInstance(controllerInterface, currentUser.Role) as IController;
		}

		var controllerClass = this.controllerTypes.Where(
			t => t.IsClass &&
				t.GetInterfaces().Contains(typeof(IController)) &&
				t.Name.Equals(controllerName + "Controller", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

		if(controllerClass != null)
		{
			return ObjectFactory.GetInstance(controllerClass) as IController;
		}

		return null;
	}
}

Then simply wire things up in your Application_Start:

protected void Application_Start()
{
	ObjectFactory.Initialize(a =>
		{
			a.For<IUserController>()
				.Use<UserController_ForModerator>()
				.Named("Moderator");

			a.For<IUserController>()
				.Use<UserController_ForAdministrator>()
				.Named("Administrator");

			// this is obviously a hack for the purposes of this post
			// here you would really be loading your real user
			a.For<User>()
				.Use(c => new User { Role = "Moderator" });
		});

	ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
}

The controller wiring can easily be done by convention in StructureMap (and other containers) so you don’t have to list each one manually.

Download the Example Code here, aren’t I nice to you?

For those of you still running IIS6 who would like to have nice SEO friendly URLs, one option is to use ISAPI Rewrite.

First, add a “.mvc” handler mapping to the asp.net dll as per Phil Haacks post.

Obviously you’ll need ISAPI Rewrite installed, then you can create the following .htaccess file:

RewriteEngine on
AllowOverride All

# Ignore Assets folder
RewriteRule ^assets/(.*?)$ /assets/$1 [NC,L]

# Rewrite everything else to have .mvc on the end of the controller name
RewriteRule ^([^/]*)(/(?:.*?)*)?$ /$1.mvc$2 [NC,L]

I keep all my CSS, images and javascript under the /assets folder. If you have these elsewhere, you probably want to modify the first rewrite rule for your specific location.

N.B. you can probably ignore these folders in a much more elegant way, perhaps with a RewriteCond on the 2nd Rule. I’m not a master of this syntax yet so this will do for the time being, it works!

Some additional rules you may also want are the following:

# Rewrite favicon
RewriteRule ^favicon.ico(.*?)$ /assets/images/icons/favicon.ico [NC,L]

# Rewrite appleicon
RewriteRule ^apple-touch-icon.png(.*?)$ /assets/images/icons/apple-touch-icon.png [NC,L]

# Ignore robots.txt
RewriteRule ^robots.txt(.*?)$ /robots.txt [NC,L]

Adding the following to your global.asax:

protected void Application_BeginRequest()
{
	if (this.Request.AppRelativeCurrentExecutionFilePath.Contains(".mvc"))
		this.Context.RewritePath(this.Request.Url.PathAndQuery.Replace(".mvc", string.Empty));
}

means you don’t need to have the .mvc in your route configurations, which keeps things nice and tidy!

jqPlot is an awesome javascript graphing library, supporting loads of cool features. Except clickable bar charts.

Here is a plugin which allows you to capture click events for bar charts.

Use it like this:

$.jqplot('Graph', data, {
	barClickable: {
		onClick: function(i, j, data){
			alert("Clicked series: " + i + ", data point: " + j + ", data: " + data);
		}
	}
});

This won’t work on horizontal or stacked graphs without modification, but it would be a fairly trivial change.

The code is available on github.

The simplest way I’ve found to encrypt data with NHibernate is to use a custom UserType which encrypts/decrypts the data on read/write.

As this post on stackoverflow demonstrates, it’s rather easy to make such a UserType. However, what I didn’t want to have to do is make a different UserType for each different property type that I want to encrypt.

Enter Encrypted<T>:

public class Encrypted<T> : PrimitiveType
{
	private readonly IEncryptionService encrypter;
	private readonly IBinaryConverter converter;

	public Encrypted() : base(new BinarySqlType())
	{
		this.encrypter = ServiceLocator.Current.GetInstance<IEncryptionService>();
		this.converter = ServiceLocator.Current.GetInstance<IBinaryConverter>();
	}

	public override string Name
	{
		get { return typeof (T).Name; }
	}

	public override Type ReturnedClass
	{
		get { return typeof (T); }
	}

	public override Type PrimitiveClass
	{
		get { return typeof (T); }
	}

	public override object DefaultValue
	{
		get { return default(T); }
	}

	public override void Set(IDbCommand cmd, object value, int index)
	{
		var serialized = this.converter.Serialize(value);
		var encrypted = this.encrypter.Encrypt(serialized);

		((IDataParameter) cmd.Parameters[index]).Value = encrypted;
	}

	public override object Get(IDataReader rs, int index)
	{
		if (rs.IsDBNull(index))
			return null;

		var encrypted = rs[index] as byte[];

		var decrypted = this.encrypter.Decrypt(encrypted);
		var deserialized = this.converter.Deserialize(decrypted);

		return deserialized;
	}

	public override object Get(IDataReader rs, string name)
	{
		return this.Get(rs, rs.GetOrdinal(name));
	}

	public override object FromStringValue(string xml)
	{
		if (xml == null)
			return null;

		if (xml.Length % 2 != 0)
			throw new ArgumentException("The string is not a valid xml representation of a binary content.", "xml");

		var bytes = new byte[xml.Length / 2];
		for (var i = 0; i < bytes.Length; i++)
		{
			var hexStr = xml.Substring(i * 2, (i + 1) * 2);
			bytes[i] = (byte) (byte.MinValue + byte.Parse(hexStr, NumberStyles.HexNumber, CultureInfo.InvariantCulture));
		}

		var decrypted = this.encrypter.Decrypt(bytes);
		var deserialized = this.converter.Deserialize(decrypted);

		return deserialized;
	}

	public override string ObjectToSQLString(object value, Dialect dialect)
	{
		var bytes = value as byte[];
		if (bytes == null)
			return "NULL";

		var builder = new StringBuilder();

		for (int i = 0; i < bytes.Length; i++)
		{
			string hexStr = (bytes[i] - byte.MinValue).ToString("x", CultureInfo.InvariantCulture);
			if (hexStr.Length == 1)
				builder.Append('0');

			builder.Append(hexStr);
		}

		return builder.ToString();
	}
}

The implementations of IBinaryConverter and IEncryptionService aren’t important for the purposes of this post, here are their signatures so you can implement then how you like:

public interface IBinaryConverter
{
	byte[] Serialize(object obj);
	object Deserialize(byte[] bytes);
}

public interface IEncryptionService
{
	byte[] Encrypt(byte[] plain);
	byte[] Decrypt(byte[] cipher);
}

I try to use natural IDs in my URIs wherever possible, like:

http://www.mydomain.com/some/resource/description

However sometimes this is not always practical, and for many of the non-public facing applications I work on it is simply unnecessary. In these cases I tend to use the GUID ID of the requested resource, like:

http://www.mydomain.com/resources/95801FAD-DA29-434F-B4EA-175C76266BB7

These 36 character GUIDs are rather ugly, here is a solution to shorten them down to 22 chars, which looks like:

http://www.mydomain.com/resources/DV0Ft9JPqkGV2Xne0Q64XA

not perfect, but much better.

N.B. My next step to shorten them further is to use a custom GUID algorithm with no machine-specific part to it, which should remove a significant number of bits. In the meantime, however…

First, we’ll introduce a ShortGuid struct based on the class described here.

public struct ShortGuid
{
	private readonly Guid guid;

	public ShortGuid(Guid guid)
	{
		this.guid = guid;
	}

	public static bool TryParse(string guid, out ShortGuid shortGuid)
	{
		Guid parsed;
		try
		{
			parsed = new Guid(Convert.FromBase64String(guid.Replace("_", "/").Replace("-", "+") + "=="));
		}
		catch
		{
			try
			{
				parsed = new Guid(guid);
			}
			catch
			{
				shortGuid = new ShortGuid();
				return false;
			}
		}

		shortGuid = new ShortGuid(parsed);
		return true;
	}

	public override string ToString()
	{
		return Convert.ToBase64String(guid.ToByteArray())
			.Substring(0, 22)
			.Replace("/", "_")
			.Replace("+", "-");
	}

	public Guid ToGuid()
	{
		return this.guid;
	}

	public static implicit operator string(ShortGuid guid)
	{
		return guid.ToString();
	}

	public static implicit operator Guid(ShortGuid shortGuid)
	{
		return shortGuid.guid;
	}
}

All pretty easy stuff. The difficulty comes when trying to get MVC to use and recognise it.

The easiest solution is to use the ShortGuid class on your resources, however the whole “short guid” concept is purely for HTTP. It certainly has no place in your domain, and has questionable presence in your resources (view models).

The next easiest solution is to use a custom route which replaces any GUID route values just before rendering, here is the code:

public class ShortGuidReplacingRoute : Route
{
	public ShortGuidReplacingRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler)
	{
	}

	public ShortGuidReplacingRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(url, defaults, routeHandler)
	{
	}

	public ShortGuidReplacingRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base(url, defaults, constraints, routeHandler)
	{
	}

	public ShortGuidReplacingRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, defaults, constraints, dataTokens, routeHandler)
	{
	}

	public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
	{
		var dictionary = new RouteValueDictionary();

		foreach(var kvp in values)
		{
			if (kvp.Value.GetType() == typeof (Guid))
				dictionary.Add(kvp.Key, new ShortGuid((Guid)kvp.Value));
			else
				dictionary.Add(kvp.Key, kvp.Value);
		}

		return base.GetVirtualPath(requestContext, dictionary);
	}
}

You then need to use this class when registering your routes, I made this convenient extension method to make life easier:

public static class RouteExtensions
{
	public static Route MapGuidReplacingRoute(this RouteCollection routes, string name, string url, object defaults)
	{
		Route route = new ShortGuidReplacingRoute(url, new MvcRouteHandler());
		route.Defaults = new RouteValueDictionary(defaults);
		route.Constraints = new RouteValueDictionary();

		routes.Add(name, route);
		return route;
	}
}

which you can use almost as normal, like so:

routes.MapGuidReplacingRoute(
	"Default",
	"{controller}/{action}/{id}",
	new { controller = "Home", action = "Index" }
	);

Then all you need is a ShortGuid model binder:

public class ShortGuidModelBinder : IModelBinder
{
	public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
	{
		if(bindingContext.ValueProvider.ContainsKey(bindingContext.ModelName))
		{
			ShortGuid shortGuid;
			var valid = ShortGuid.TryParse(bindingContext.ValueProvider[bindingContext.ModelName].AttemptedValue, out shortGuid);

			if (valid)
			{
				if(bindingContext.ModelType == typeof(Guid))
					return shortGuid.ToGuid();

				if (bindingContext.ModelType == typeof(ShortGuid))
					return shortGuid;
			}
		}

		return Guid.Empty;
	}
}

Which you register in the normal way:

ModelBinders.Binders[typeof (Guid)] = new ShortGuidModelBinder();

Job done :)

There are plenty of discussions on why you should do this, which I’m not going to cover here.

What I am interested in discussing is a solution to the endless overriding of Equals and GetHashCode in each of your entities. Not only does this pollute the object with noise, but its a nightmare to maintain.

I use GUIDs for my Id columns, which is very convenient as you don’t have to goto the database for clues as to what the next unique ID may be.

Normally, when overriding GetHashCode you have to compare all your entity’s properties and when comparing for equality, you have to do the same because transient objects don’t yet have an ID.

This got me thinking, why even bother letting NH assign the ID? If you create the ID in your entities’ constructor GetHashCode and Equals become very easily overridden and can be abstracted to a base class, like so:

public abstract class Entity
{
	public virtual Guid Id { get; protected set; }

	protected Entity()
	{
		this.Id = Guid.NewGuid();
	}

	public override int GetHashCode()
	{
		return this.Id.GetHashCode();
	}

	public override bool Equals(object obj)
	{
		if (ReferenceEquals(this, obj))
			return true;

		var entity = obj as Entity;
		if (ReferenceEquals(null, entity))
			return false;

		return entity.Id.Equals(this.Id);
	}
}

For this to work, you must set your NHibernate ID Generator mapping to “Assigned”, like so:

<id name="Id" type="System.Guid">
    <column name="Id" />
    <generator class="assigned" />
</id>

For all you optimizers out there, you can still use alternate GUID algorithms like Comb :)

Thoughts?