Skip navigation

I’m in the process of moving my email handling from google apps over to mailgun, mainly because I really need web hooks to support new customer dashboard functionality.

Since my search for some proper .Net library resulted in basically nothing, I decided to roll one myself: mnailgun (I know, the ‘n’ should come first, but I liked this version more ;-P). And while I was at it, I thought, well why not do it in the open as well? So here you go: The source code is available on github and a nuget package is available as well.

For some reason searching for ‘mnailgun’ on the nuget site results in an empty list, while searching for it in Visual Studio when adding a package reference, seems to work just fine… Anyone know why?

If, for whatever reason (I’m not going into this discussion), you’d like to inject your dependencies at the method level instead of using your constructor, like so:


public ActionResult Post(Whatever whatever, IMyDependency dependency)
{
	// use dependency here
}

Just create these two classes:

public class DependencyModelBinderProvider : IModelBinderProvider
{
	public IModelBinder GetBinder(Type modelType)
	{
		return modelType.IsAbstract ? new DependencyModelBinder() : null;
	}
}

public class DependencyModelBinder : IModelBinder
{
	object IModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
	{
		return DependencyResolver.Current.GetService(bindingContext.ModelType);
	}
}

And, of course, at bootstrap/app start time:

ModelBinderProviders.BinderProviders.Add(new DependencyModelBinderProvider());

VoilĂ , DI at method level in 2 minutes!

I was almost going crazy before I found out that when you use a PreApplicationStartMethodAttribute for bootstrapping your hosting environment you must point to a type that resides in the same assembly that is being decorated!

Pointing to types in a different assembly will just blow up with a YSOD saying ‘The method specified by the PreApplicationStartMethodAttribute on assembly ‘assembly name’ cannot be resolved. Type: ‘type name’, MethodName: ‘Initialize’. Verify that the type is public and the method is public and static (Shared in Visual Basic).’.

Just though I’d mention it here, there’s not to much info on this…

Today I decided to finally formalize my staging process a bit more than I used to and started setting up a new test (for starters) environment from scratch. The environment I need is not very demanding: basically, I just need W2008R2 (incl. IIS 7.5) and .Net 4.0. However, for deployment purposes I’d also like (amongst some other things which don’t really matter now) an SSH server on my boxes.

I’ve been using openssh (the one that comes with the Cygwin project) for quite some time now and, up until now, I’ve always installed it manually. The installation is pretty simple, but every time I do such an installation it takes me a few retries before I remember every step exactly, not very efficient… And, anyway, why do anything manually when you can automate it, especially when it’s as simple as this:

  1. Download the Cygwin installer and save it to a folder were you want to run your installation from
  2. Put the following lines in a windows batch file, let’s say install-ssh.bat (alongside the setup.exe)
setup.exe --quiet-mode --root C:\cygwin --site http://<the closest source to you> --packages openssh
cd c:\cygwin\bin
bash --login -c "/bin/ssh-host-config -y -c ntsec -u sshd_account -w <your password here>"
bash --login -c "/bin/ssh-user-config -y -p <your password here>"
sed -i.bak "s/#.*PasswordAuthentication.*yes/PasswordAuthentication no/" /etc/sshd_config
netsh advfirewall firewall add rule name=SSH dir=in action=allow protocol=tcp localport=22
net start sshd

Now, issuing install-ssh at the command line should install openssh and start the sshd service in less then a minute…

What happened?

The first line simply runs the cygwin installer without requiring user interaction. When you run it, you’ll notice that the install wizard will show, but without you having to ‘push the buttons’ — I don’t know if there’s a way to hide the GUI as well, I didn’t mind. The command line options speak for them selves, I guess.

After the installation is done I change my working dir to the bin folder of cygwin. This isn’t important, it’s just a convenience, it allows me to call bash without the full path…

Next, we configure the ssh host with predefined options, instead of getting prompts. The options I’m using are:

  • confirm all queries with yes (-y)
  • instruct cygwin to use Windows’ security rules for controlling users’ access to files and other operating system facilities (-c ntsec)
  • create a new local (priviledged) account ‘sshd_account’ with the specified password (-u sshd_account -w )

The ssh-user-config script is executed to generate a new private and public key pair for the current user with the specified passphrase to protect the private key. I’m fine with moving the generated private key to my deployment server in order to connect, but you don’t have to, you could even skip this command if you’re fine with username password authentication.

The sed command is related to the previous one: it simply disables password authentication by substituting the appropriate commented-out option in the sshd configuration file.

Finally, before starting the sshd service, I’m adding a firewall rule to accept incoming traffic on the default ssh port.

Connecting from a client

As mentioned above, I’m fine with moving the generated private key to my local deployment server. One reason for this (and not using some previously generate key-pair) is that it helps avoiding deploying to the wrong environment by mistake, the all have their dedicated key — no guarantee, of course. So, what I’m doing is copying the /home/user/.ssh/id_rsa file to my local depoyment server as env-user.key and connect using the following command:

ssh -i /path/to/env-user.key user@remote_host

For deployment I’m actually using a rake task that uses the SharpSsh .Net library (I’m using IronRuby).

Disclaimer

I’m not guaranteeing this will work in any given environment, but I’ve tested this on my Windows 7 and Windows 2008 R2 boxes, works like a charm for me…

I’m gonna spare you the details of the edge-case issues I ran into (in a nutshell: they involve loading assemblies from other directories that load other assemblies from yet other directories causing things to act real strange in DLR-land), but here a little trick…
If for some reason you would like to load/require an assembly in IronRuby in the Load and not the LoadFrom context then instead of just doing this (which is, by the way, in most cases, the best thing to do):

require '.\some\path\assembly.name.dll'

do something like this:

def do_in(working_dir)
	dir = Dir.pwd
	Dir.chdir working_dir
	yield
	Dir.chdir dir
end

do_in '.\some\path' do require 'assembly.name' end

Works like a charm…

Note: If the code in your loaded assembly loads other things at runtime, you’ll have to do that work in the do_in block as wel, of course. Like this:

do_in '.\some\path' do
  require 'Assembly.Name'
  Assembly::Name::Type.new(foo, bar) # this loads more stuff at runtime
end

Just thought I’d mention that I published an updated version (0.3.0) of inetmgr. Check out the release notes on github for more information.

The main addition is the possibility to update site-level configuration (web.config) as well now.

By the way, happy 2011!

I know, this is a dead place. Unfortunately, I just can’t seem to find the time to put more time into this blog… at least at this time. Anyway, the thing that is stealing most of my “free” time made me do some experiments that I thought were worth sharing.

Since quite some time now I’ve been pretty interested in that awesome programming language called Ruby — they say it’s a .Net developer disease :-), but I don’t know if that’s true. After having read a few books on the topic (on my trustworthy iLead) and some fiddling around with irb, I decided to get some “real” hands-on. So I started with a minimal-near-to-flat-learning-curve-project and migrated my build scripts to Rake (using Albacore). Bye bye XML-based build scripts!

Then I thought, why not add some deploy stuff to my build? And so I began investigating the possibilities to configure IIS (7.5) with Ruby (and Rake) which lead me to creating my first ruby library ‘inetmgr‘! You can read more about it on the inetmgr about page.

There’s quite some annoyence about how ASP.Net routing handles trailing slashes. I agree, it would have been nice if one could enforce whether or not to use a trailing slash.

I’ve always taken good care of my trailing slashes. Almost every link comes from my custom UrlHelper or extension methods (for convenience – e.g. Model.Product.GetThumbnailUrl()). Anyway, that doesn’t mean it stopped bugging me! For one, external links (SEO) are not under your control, I don’t really know how serious this duplicate content issue is, but I’m not willing to take a chance on it. Another unsolved annoyence is when you add content pages. You always have to think twice about trailing slashes in every little link you include.

This week, I thought it was about time to go for a more generic solution. I started by googling for it and almost ended up using the new IIS7 URL Rewrite Module just like Scott suggested in his post. The main reason I didn’t was because I hate managing things in two places. Especially when their so closely related.

And then I thought: Why not let the system do what you ask it to do? How hard can it be to make the system respect you route mappings? If I map a route with url "{category}/" or "{category}/{product}" I want to make sure category urls end with a slash and products don’t. That simple.

It seemed to me that tuning ASP.Net MVC’s UrlRoutingModule was the most abvious thing to do, so here’s what I’ve done:

public class UrlRoutingModule : System.Web.Routing.UrlRoutingModule
{
	private const string SLASH = "/";

	public override void PostResolveRequestCache(HttpContextBase context)
	{
		var routeData = RouteCollection.GetRouteData(context);

		var redirecturi = GetRedirectUri(routeData, context.Request.Url);

		if (redirecturi != null)
		{
			context.Response.RedirectPermanently(redirecturi);
			return;
		}

		base.PostResolveRequestCache(context);
	}

	private static Uri GetRedirectUri(RouteData routeData, Uri requestedUri)
	{
		if (routeData == null) return null;

		var route = routeData.Route as Route;
		if (route == null) return null;

		var requestedSegments = GetSegmentCount(requestedUri.AbsolutePath);
		var mappedSegements = GetSegmentCount(route.Url);

		if (requestedSegments == mappedSegements)
		{
			var slashRequired = route.Url.EndsWith(SLASH);

			if (slashRequired && !requestedUri.AbsolutePath.EndsWith(SLASH))
				return requestedUri.Append(SLASH);

			if (!slashRequired && requestedUri.AbsolutePath.EndsWith(SLASH))
				return requestedUri.TrimPathEnd(SLASH[0]);
		}
		else if (!requestedUri.AbsolutePath.EndsWith(SLASH)) // requestedSegments < mappedSegements
		{
			return requestedUri.Append(SLASH);
		}

		return null;
	}

	private static int GetSegmentCount(string path)
	{
		return path.Split(SLASH.ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Length;
	}
}

Note: If your route ends with optional segments, urls that don’t include them always end up with a trailing slash.

Another note: The Append and TrimPathEnd are Uri extension methods:

public static class UriExtensions
{
	public static Uri Append(this Uri uri, string value)
	{
		return new Uri(GetAbsoluteUriWithoutQuery(uri) + value + uri.Query);
	}

	public static Uri TrimPathEnd(this Uri uri, params char[] trimChars)
	{
		return new Uri(GetAbsoluteUriWithoutQuery(uri).TrimEnd(trimChars) + uri.Query);
	}

	private static string GetAbsoluteUriWithoutQuery(Uri uri)
	{
		var ret = uri.AbsoluteUri;
		if (uri.Query.Length > 0) ret = ret.Substring(0, ret.Length - uri.Query.Length);
		return ret;
	}
}

One more note:: I’m fully aware that this module alone does not solve the entire trailing slash problem, but minor additional (possibly project-specific) things like a custom UrlHelper (what I did/had to do, I spare you the details) or solutions like this method are easy enough to make it complete.

It wasn’t until a few weeks ago that I discovered that Castle has this facility that manages WCF client proxies. I knew there was a server-side facility but the client stuff was new to me. Very well, but at this moment however, I’m using LinFu, which is really great, but does not have this feature (at least, I couldn’t find it). With the excuse of getting to know a bit more about LinFu, I decided to quickly put it together myself…

Before you continue, you must know that the following implementation only incorporates my specific requirements (I’m certain they’re the most common, but nonetheless). It does not care about sessions, duplex communication or any of that. I’ve got a failry conservative service layer with services that are instantiated per call and since they are (almost) at the use case level, it is not very likely that client code performs subsequent calls on a single proxy instance. Subsequent calls are possible but a new channel is created each time.

Until today I used to revert to a ServiceHelper class which provided some extension methods that accepted Action<T> or Func<T,TResult> lambda’s that where called inside a try, catch, finally block to make sure we dispose the channel properly. I never really liked this way of working, it is cumbersome and doesn’t abstract away the fact that you’re dealing with WCF services. Additionally, I was not able to inject WCF services neither. Am I glad that’s over!

Ok, how does it work? Well, after creating a container, all you have to do is this:

container.PreProcessors.Add(new ClientChannelPreProcessor());

This line of code above makes sure the LinFu container calls a pre-processor whenever a service interface needs to be resolved.

public class ClientChannelPreProcessor : IPreProcessor
{
	public void Preprocess(IServiceRequest request)
	{
		if (request.ServiceType.IsDefined(typeof(ServiceContractAttribute), true))
			request.ActualFactory = new ClientChannelFactory();
	}
}

This pre-processor couldn’t be more straight-forward: If we need to resolve a ServiceContract interface, don’t use the default service factory, but a custom one. Well, actually, there is no default service factory; request.ActualFactory is null because we didn’t register the service, we don’t need to.

public class ClientChannelFactory : IFactory
{
	public object CreateInstance(IFactoryRequest request)
	{
		if (!request.ServiceType.IsDefined(typeof(ServiceContractAttribute), true))
			throw new InvalidOperationException("The ClientChannelFactory is intended for WCF services only.");

		var factory = new ProxyFactory();
		var interceptor = new ClientChannelInterceptor(request.ServiceType, request.ServiceName);

		return factory.CreateProxy(request.ServiceType, interceptor);
	}
}

The client channel factory first creates an interceptor that knows about the interface type and the requested service name, if any. It then creates a dynamic proxy with the interceptor and returns is as the resolved service.

Finally, we have our interceptor that performs the actual service calls by creating the channel right before the actual service call is performed. After the call the channel is disposed by Closing or aborting it as necessary.

public class ClientChannelInterceptor : IInterceptor
{
	private readonly Func<object> CreateChannel;

	public ClientChannelInterceptor(Type serviceType, string instanceName)
	{
		CreateChannel = GetChannelCreationDelegate(serviceType, instanceName);
	}

	public object Intercept(IInvocationInfo info)
	{
		var target = CreateChannel();

		try
		{
			return info.TargetMethod.Invoke(target, info.Arguments);
		}
		finally
		{
			DisposeServiceInstance(target);
		}
	}

	private static void DisposeServiceInstance(object target)
	{
		var client = target as IClientChannel;

		if (client == null || client.State == CommunicationState.Closed) return;

		try
		{
			client.Close();
		}
		catch
		{
			client.Abort();
		}
	}

	private static Func<object> GetChannelCreationDelegate(Type interfaceType, string name)
	{
		if (name == null) name = ""; // revert to default endpoint

		var factoryType = typeof(ChannelFactory<>).MakeGenericType(interfaceType);
		var factory = Activator.CreateInstance(factoryType, name);
		var createChannelMethod = factoryType.GetMethod("CreateChannel", Type.EmptyTypes);

		return (Func<object>)Delegate.CreateDelegate(typeof(Func<object>), factory, createChannelMethod);
	}
}

One last thing about resolving services with instance names. If you resolve services without specifying an instance name (which is most likely), the ChannelFactory will create a proxy for the configured endpoint that has no name. If you specify a name it must be the name of an endpoint in your configuration file.

And that is why we need to write clean code

Just watched (diagonally) the NDC presentation of Robert C. Martin. Very nicely put!

Follow

Get every new post delivered to your Inbox.