Routing with MonoRail's New Routing Engine


Yesterday I was having a bit of  trouble figuring out how to use MonoRail's new routing engine. There's no documentation on it other than this post by Hammet, but it's outdated and doesn't reflect the current state of the routing engine. I ended up reading through MonoRail's routing tests, and afterwords I felt like I had a very good understanding of how to use the new engine.

First, you need to register the routing module with ASP.Net:

    <system.web>
        <httpModules>
            <add name="routing" type="Castle.MonoRail.Framework.Routing.RoutingModuleEx, Castle.MonoRail.Framework"/>
        </httpModules>
    </system.web>

You can register routes in the Application_Start method of your Global application class. The routes themselves are fairly easy to understand.

    RoutingModuleEx.Engine.Add(
        new PatternRoute("default", "<area>/[controller]/[action]")
            .DefaultForController().Is("home")
            .DefaultForAction().Is("index")
    );

Here, I've registered a new pattern route named "default" (naming your routes is optional, by the way). '<' and '>' denote required parts of a url, while '[' and ']' denote optional parts. The "area", "controller", and "action" parts are special in that the routing engine uses them to determine the selected area, controller, and action respsectively. The other named parts will be passed to the selected action as parameters. With this particular route, I can completely leave off the controller and action parts, as they are optional. If ommited, they will default to "home" and "index" respectively. As an example, browsing to "/admin/" would result in a request to "/admin/home/index.rails", while browsing to "/admin/somecontroller" would result in a request to "/admin/somecontroller/index.rails".

You can also set up various restrictions for the different parts of the url.

    RoutingModuleEx.Engine.Add(
        new PatternRoute("show", "<controller>/<id>/[action]")
            .Restrict("id").ValidInteger
            .DefaultForAction().Is("show")
    );

The above route will match the following example urls:

/employee/3454/    (Maps to: /employee/show.rails?id=3454)
/employee/1337/payrollinfo/    (Maps to: /employee/payrollinfo.rails?id=1337)

But it will fail for these:

/employee/fadsfadsfjdaslkjfdas
/employee/this-is-not-an-integer/payrollinfo

The order in which you register your routes is also important, and will affect the outcome of the routing. When the engine tries to route a url, it tries to match each route in the order they were registered. If the incoming URL matches a route, that route is selected and routing stops. This means that sometimes you need to keep an eye on the order in which you register your routes, or sometimes you may get results that aren't quite what you were going for.

author: Nick | posted @ Wednesday, May 14, 2008 5:33 PM | Feedback (0)

Parameter Validation and Generic Specialization (kind of) Using Extension Methods


Parameter Validation and Generic Specialization (kind of) Through Extension Methods

Lately I've been trying to work out a few kinks in my own coding practices, trying to make them more robust and flexible. One area that I've been working on during the past week has been parameter validation for public methods. Until recently, I'd been using a class similar to the following:

    public static class Guard {
public static void AgainstNull<T>(string parameterName, T value) where T : class {
if (value == null) {
throw new ArgumentNullException(parameterName);
}
}

public static viod AgainstNullOrEmpty(string parameterName, string value) {
if (string.IsNullOrempty(value)) {
throw new ArgumentException(parameterName);
}
}

/* etc... */ }


You would use it as follows:

    public void SomePublicMethodRequiringParameterValidation(string str, object obj) {
Guard.AgainstNullOrEmpty("str", str);
Guard.AgainstNull("obj", obj);
/* etc... */ /* method body */ }

This works fairly well, but I wasn't satisfied with how it flowed. It's also not very extensible. It's hard to add new validation methods to the Guard class unless it's part of the project I'm working on.

So I tried something new:

public static class Ensure {
public static void IsGreaterThan<T>(this Ensurable<T> ensurable, T value) where T : IComparable<T> {
if (ensurable.Value.CompareTo(value) <= 0) {
throw new ArgumentOutOfRangeException(ensurable.Name);
}
}

public static void IsLessThan<T>(this Ensurable<T> ensurable, T value) where T : IComparable<T> {
if (ensurable.Value.CompareTo(value) >= 0) {
throw new ArgumentOutOfRangeException(ensurable.Name);
}
}

public static void IsEqualTo<T>(this Ensurable<T> ensurable, T value) where T : IEquatable<T> {
if (!ensurable.Value.Equals(value)) {
throw new ArgumentOutOfRangeException(ensurable.Name);
}
}

public static void IsNotNullOrEmpty(this Ensurable<string> ensurable) {
ensurable.IsNotNull();

if (ensurable.Value == "") {
throw new ArgumentException("Value cannot be empty.", ensurable.Name);
}
}

public static void IsNotNull<T>(this Ensurable<T> ensurable) where T : class {
if (ensurable.Value == null) {
throw new ArgumentNullException(ensurable.Name);
}
}

public static Ensurable<T> That<T>(string name, T value) {
return new Ensurable<T>(name, value);
}
}

public class Ensurable<T> {
public Ensurable(string name, T value) {
Name = name;
Value = value;
}

public string Name { get; private set; }
public T Value { get; private set; }
}


I find that this is much more useful. First of all, look at how well the validation flows:

    public void SomeMethod(string str, object obj, int i) {
Ensure.That("str", str).IsNotNullOrEmpty();
Ensure.That("obj", obj).IsNotNull();
Ensure.That("i", i).IsGreaterThan(0);
}


The interface is pretty fluent, which makes for good readability (in this case, at least). But, more imporantly, it's much more extensible than the Guard class. I can extend my parameter validation using my own extension methods, without modifying the underlying classes one bit.

    public static class EnsureExtensions {
public static void Between(this Ensurable<DateTime> ensurable, DateTime low, DateTime high) {
if (ensurable.Value < low || ensurable.Value > high) {
throw new ArgumentOufOfRangeException(ensurable.Name);
}
}
}


Occasionally I need to validate parameters using a condition that's not very common, or may even be specific to my problem domain. That's where this extensibility mechanism is a perfect fit.

Futhermore, this method allows us to define methods on Ensurable that will only work for a specific T. If I am validating a string, the IsNotNullOrEmpty method is available and will show up with intellisense. If I am validating something that implements IComparable, then the IsGreaterThan and IsLessThan methods will show up. If I'm validating a parameter of type object, none of the above will appear, but IsNotNull and IsEqualTo will still appear. It's almost like having generic specialization, but not quite.

author: Nick | posted @ Wednesday, April 23, 2008 10:57 AM | Feedback (2)

MVC-Related Mono Bugs Have Been Fixed


In my last post I discussed in detail several Mono bugs that prevented the current drop of System.Web.Mvc from running, and ways to work around those bugs.

Yesterday, I received the following email:
Hey Nick,

Just writing to let you know that I've fixed the two bugs you mentioned in your detailed description of how to run MVC under Mono (the HttpContext.Handler and the DefaultVirtualPathProvider). With the current version of mono from svn trunk, you can run the sample MVC application generated by VS2008 without virtually any changes.
The only thing you need to do is to comment out entry for the System.Data.DataSetExtensions assembly, which doesn't exist on Mono yet. After doing that the application will run just like under .NET.

Thanks for your effort :) - if you have time, it would be great if you could test your MVC apps with svn trunk of mono and let me know if you found any other bugs :)

-Marek Habersack
I haven't actually played with the current Mono trunk yet, but it sounds like the two bugs I described have been fixed. I'd like to thank Marek for fixing these bugs.

ASP.Net MVC should now run on the Mono trunk without any workarounds!

author: Nick | posted @ Thursday, March 13, 2008 10:10 AM | Feedback (0)

How to Run ASP.Net MVC on Mono


This is a follow up to my previous post about running the new ASP.Net MVC framework on top of Mono.

Firstly, you'll need CTP 2 of the ASP.Net MVC framework, which you can get here. I'm going to assume that you know enough about ASP.Net to make the changes I describe. If you need more information about the MVC framework http://asp.net/mvc/ has some excellent information on it.

Secondly, you'll need to be running an up-to-date version of Mono. At this time, the last official release is 1.2.6, which doesn't have all of the required dependencies. I am running preview 4 of Mono 1.9. The latest preview can be found here.

Thirdly, for this to work your application can't depend upon anything that's not supported in Mono. I had to remove some references to System.Web.Extensions, System.Data.DataSetExtensions, and System.Data.Linq from my Web.config file in order for this to work. I would reccomend removing those references from your project as well.


<compilation debug="false">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<!--<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>-->
<add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<!--<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>-->
<!--<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>-->
<!--<add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />-->
</
assemblies>
</
compilation>

Now, down to business.

Mono's HttpApplication Implementation


The System.Web.Mvc assembly depends upon the System.Web.Routing assembly for (you guessed it) routing. Obviously, this means that System.Web.Routing needs to work with Mono if we are to even have hope of getting System.Web.Mvc to run on it. In order to take advantage of the routing capabilities of System.Web.Routing, you register the System.Web.Routing.UrlRoutingModule class with the ASP.Net runtime. UrlRoutingModule takes incoming requests and routes them to the appropriate IHttpHandler implementation. If you try to run the MVC sample app on Mono unmodified, UrlRoutingModule won't work and you'll get lots of 404's.

I tried to write my own routing module, but I became frustrated when I couldn't get it working after about half an hour. After digging a little deeper and walking walking through Mono's HTTP request pipeline, I found an inconsistency between Mono's HttpApplication implementation and the one that ships with the .Net Framework. The .Net implemenation allows you to use HttpContext.Handler from an IHttpModule to set which IHttpHandler will be used to process a request. The Mono implementation does not; it seems to always resolve the handler based on the extension of the requested URL. UrlRoutingModule is apparently using HttpContext.Handler to specify which IHttpHandler should handle the request, which means that it doesn't work with Mono. This is also the reason my custom routing module wouldn't work.

All is not lost, however. We can override Mono's default IHttpHandler resolution using an IHttpHandlerFactory. This means, however that our factory has to do all of the routing work that UrlRoutingModule would have done for us. It's actually not that much code though.

	public class MvcHttpHandlerFactory : IHttpHandlerFactory {
public IHttpHandler GetHandler(HttpContext httpContext, string requestType, string url, string pathTranslated) {
var context = new HttpContextWrapper2(httpContext);

using(RouteTable.Routes.GetReadLock()) {
var routeData = RouteTable.Routes.GetRouteData(context);

if (routeData == null) {
throw new InvalidOperationException("Invalid route data.");
}

var routeHandler = routeData.RouteHandler;

if (routeHandler == null) {
throw new InvalidOperationException("Invalid route handler.");
}

var requestContext = new RequestContext(context, routeData);
return routeHandler.GetHttpHandler(requestContext);
}
}

public void ReleaseHandler(IHttpHandler handler) {
if (handler is IDisposable) {
((IDisposable)handler).Dispose();
}
}
}

    <httpHandlers>         
<!-- snip -->
<
add verb="*" path="*.mvc*" type="MvcOnMono.MvcHttpHandlerFactory, MvcOnMono"/>
</
httpHandlers>

One side-effect of this is that we have to adjust the routes for our controllers to use some kind of extension (I'm using ".mvc"). We have to map our IHttpHandlerFactory to a set of paths, and it can't be *.* because then Mono doesn't handle static files correctly. Another side-effect is that /Default.aspx will no longer map to the Home controller, since our factory doesn't perform routing for .aspx files. Using an IHttpModule would remove these limitations, but as we already saw that's not currenlty possible with Mono.

Here's what the routes should look like in order to run the sample application:

	public static void RegisterRoutes(RouteCollection routes) {
// Note: Change the URL to "{controller}.mvc/{action}/{id}" to enable
// automatic support on IIS6 and IIS7 classic mode

routes.Add(new Route("{controller}.mvc/{action}/{id}", new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(new { action = "Index", id = "" }),
});

routes.Add(new Route("Default.aspx", new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
});
}


Now, I have no idea if this is the right way to route the requests using System.Web.Routing, since there's not really any documentation for it yet. It seems to work fine for now though. Please let me know if you spot any problems :)

You should be able to run the sample app on .Net at this point by browsing to "/Home.mvc/". It won't work on Mono just yet, but if it doesn't work on .Net then you probably need to fix something before it will work on Mono.

Mono's DefaultVirtualPathProvider


At this point, if you try to run the appliction on Mono's XSP2 web server, you will get the following error.

Virtual Path Error

After a quick look at the Mono source, I disovered the following in System.Web.Hosting.DefaultVirtualPathProvider:

	if (UrlUtils.IsRelativeUrl (virtualPath))
throw new ArgumentException (String.Concat ("The relative virtual path '", virtualPath, "', is not allowed here."));


I'm not sure why this is in there, but it's not that hard to circumvent. We just need to create our own VirtualPathProvider that can actually deal with application-relative paths, and register it with the System.Web.Hosting.HostingEnvironment class.

	public class MvcVirtualPathProvider : VirtualPathProvider {
public override bool FileExists(string virtualPath) {
if (VirtualPathUtility.IsAppRelative(virtualPath)) {
var physical = HostingEnvironment.MapPath(virtualPath);

if (File.Exists(physical))
return true;
}

return Previous != null && Previous.FileExists(virtualPath);
}
}
	protected void Application_Start(object sender, EventArgs e) {
RegisterRoutes(RouteTable.Routes);
HostingEnvironment.RegisterVirtualPathProvider(new MvcVirtualPathProvider());
}

That's it! That's all you have to do! You should now be able to browse to "/Home.mvc" in the sample app while running Mon's XSP2 web server and it should run just fine.

If you want the code, you can download the Mono-ready MVC sample application here.

Conclusion

This really isn't that much code. As far as I can tell, all the Mono team would need to do to make MVC work without any tweaking is fix their HttpApplication implementation and change their default VirtualPathProvider to correctly deal with app-relative paths.

Something I noticed while working on this was that when I clicked "About" in the MVC sample app the site's CSS file would fail to load. Apparently, putting the ".mvc" extension on the controller part of the route causes the .Net implementation to do something funky with the CSS file's virtual path. It seems to work fine in the Mono implementation though. I'm not sure which is correct, but Mono behaved the way I was expecting, while the .Net Framework crapped out.

I haven't tested this on Linux with mod_mono yet, so if you end up doing so please let everyone know if it works. I don't see any reason it shouldn't, but I might be missing something.

author: Nick | posted @ Wednesday, March 12, 2008 9:55 AM | Feedback (4)

Running ASP.Net MVC on Mono


UPDATE: See this post for more details on running MVC on Mono.

I've been playing around quite a bit with the second CTP of the new ASP.Net MVC framework. Something that's really important to me right now is that we eventually get an implementation of this running on Mono.

But, it turns out that Mono might not need its own separate implementation after all...

With a little bit of tweaking, the current build of MVC actually runs on top of Mono without modification! There are several inconsistencies (bugs, perhaps?) in Mono's System.Web implementation that neccessitate a little bit of hacking in order to get this working. However, it's not actually that bad, and I think with a small amount of effort the Mono team could probably make this work without any tweaking at all. I'll post more details on specifically what I had to do to get this working later.

Breaking out MVC from the rest of System.Web.Extensions is basically what made this even possible. There was no way to get drop 1 of MVC working on Mono, because their version of System.Web.Extensions had too many dependencies that aren't implemented in Mono yet. All of that has been solved with drop 2, however.

I wonder if the MVC team would be willing to make their implementation a little bit more Mono friendly? Realistically, either team could make this work, but it would be cool to see the MVC team working with the Mono team, and it might save a little bit of work.

My next post will contain the specifics on how to get MVC running on Mono, so stay tuned.

author: Nick | posted @ Tuesday, March 11, 2008 7:54 PM | Feedback (7)

ASP.Net Repeaters Suck


For loops FTW.


Check out that intellisense awesomeness. Note the complete lack of casts and Eval.

author: Nick | posted @ Monday, March 03, 2008 3:50 PM | Feedback (7)

The Importance of Code Reviews and Database-Level Isolation


For the past few days I've been dealing with several massive security concerns. Classic ASP made it very easy to attack websites using SQL injection, and most IT personnel still have no idea what SQL injection is. This, in conjunction with horrible database architecture and bad practices in general, has led to an overwhelming wave of attacks against some of our web applications.

Most of the code that is responsible for this was written many years ago (some code is over 5 years old).  There are literally hundreds of pages that are vulnerable, and they all access the same database.  What's worse is that there are actually other domains that we're responsible for that access the same database with the same credentials. All of this is making it nearly impossible to determine which pages are under attack, and by who.

This entire headache could have been avoided through some very simple decisions and practices.

Keep up-to-date on security vulnerabilities.

Crackers don't stop cracking, so we can't stop learning about their latest techniques. Knowing you have a potential vulnerability is the first step to securing it before it is exploited.

Every piece of code written by someone other than a competent software developer needs to be reviewed by a competent software developer before going live.

Much of this code was written either by interns or webmasters (i.e. not software developers). Interns are here to learn, so you can't expect them to produce production quality code (indeed, you should expect your interns to produce code that is absolutely not production quality). Webmasters are also typically not very good software developers and tend to focus more on things like website design and updates, so you shouldn't really trust their code either. I'm not dissing webmasters, they just have a different job. Believe me, I'm no designer, and I would hope that you wouldn't trust my designs as much as you would trust a good webmaster's.

You don't have to be a lead software architect to find things like SQL injection vulnerabilities. The most important thing is making sure each piece of code passes under the eyes of someone who can spot common programming mistakes that will lead to later security holes.

Keep your attack surface as small as possible, and isolate individual concerns (applications or logical groups of pages) at the database level.

This point is a little bit more abstract. One thing we're doing right now is changing the most common database users to have read-only permissions. This will probably fix 95% of our security holes (though they will still throw application-level errors). Pages that need to write to the database will have to use a separate login. This effectively reduces our attack surface to only those pages which need to modify the database.

We could also isolate each application with their own separate logins, or even their own databases. This would allow us to much more easily ascertain which pages have holes, and would restrict the attacker to a single database or set of tables. This is the route I would have likely taken if I was starting from scratch. Each website would have its own database, and each "application" would have its own credentials. Application credentials would be restricted to the bare minimum level of permissions required to operate normally.

Bad stuff happens when vulnerability gets out of hand. Don't let it happen to you.

author: Nick | posted @ Monday, March 03, 2008 2:04 PM | Feedback (1)

Filenames for Generic Classes


Until now, I've pretty much always named my code files with the name of the class or interface they contain, disregarding any type parameters for generic types.  Once upon a time I started naming generic class files with a ".generic.cs" extension (I believe the Castle Project adopts this naming convention) , but that got old really quick. 

Today, I think I've finally found a naming convention for generic files that I can be satisfied with:  <type-name>[<generic-parameter-list>].cs

For example:  IEnumerable[T].cs, IDictionary[TKey, TValue].cs, etc.

I'm considering putting "of" in there before the type parameters (e.g. SomeType[of T]) because it matches Boo's generic syntax, but I'm not sure I like that.

w00t!

author: Nick | posted @ Wednesday, February 20, 2008 10:32 AM | Feedback (1)

Upcomming Code Stuff and Other Related Awesomeness


Firstly, I'm extremely pleased with the way my work machine has been running now that it's been cleaned up. Between disabling a bunch of unused services and using Autoruns to disable craploads of unnecessary and invasive startup processes I think my productivity has gone up by about 10 percent. Seriously, it was getting that bad. Now I just have to kick my old habits of expecting certain actions to take several seconds to complete. For example, Visual Studio 2008 used to take over 5 seconds to delete a single file from my machine. There were times when I would delete a group of files, go the the break room to grab some coffee, come back, and still be waiting for it to finish. I still don't know what was causing that particular behavior, but it's gone now and I feel so free :D

Secondly, I've been tinkering with ASP.Net MVC quite a bit lately. So far I really like it. There are a few bugs and missing features, but it's not even in beta yet. For a CTP I'm damned impressed. However, I'm even more excited about the upcomming CTP release that's going to be released at MIX 08 in a couple of weeks.

If what Scott Gu says is true, we may be able to get System.Web.Mvc running on top of Mono without too much effort. He mentions a mysterious System.Web.Mvc.dll which doesn't actually exist in the current CTP (System.Web.Mvc is in System.Web.Extensions.dll). This, in conjunction with the ability to deploy ASP.Net MVC into the /bin folder without installation on the server, leads me to believe that they may have broken the System.Web.Mvc namespace out into its own assembly. I have already tried to get System.Web.Mvc running on Mono, but the System.Web.Extensions assembly just has too many dependencies (over 1000) that don't exist in Mono yet. From what I can tell, however, the System.Web.Mvc namespace only has one. Take all of this and combine it with number 8 on Scott Gu's MVC roadmap and it might be very trivial to get this running on top of Mono.

System.Web.Mvc on top of Mono would make me very, very, very excited.

author: Nick | posted @ Tuesday, February 19, 2008 4:27 PM | Feedback (0)

Awesomeness




That's 21 including Task Manager.  Since I normally don't have the Task Manager window open unless I'm using it, this means I'm down to 20 processes (down from almost 40).  My computer is much faster now, and it's extremely noticeable.  And, to top it all off, I didn't really have to disable anything that is necessary for day-to-day stuff.

I'm thinking I might axe Outlook as well and use the web client.  It's almost as feature rich, and I don't use most of the features of Outlook anyways.  If this wasn't a work machine I would also get rid of uphclean.exe, taking me down to 19.

While working that number rarely goes above 25 now (Firefox, Visual Studio + Web Dev Server, another instance of Explorer, and Query Analyzer).

author: Nick | posted @ Wednesday, February 13, 2008 5:54 PM | Feedback (2)