Tigraine
Daniel Hoelbling talks about .NET

Castle.Pagination v1.1.0 released

December 5th, 2009 . by Daniel Hölbling

Finally the Castle.Pagination component has reached v1.1.0 and is ready to be incorporated into the upcoming Castle Monorail 2.0 release.

As for the changes: There are hardly any. Pagination is a solved problem and most of the code changes where bug fixes and minor improvements.

Anyway, thanks Jonathan Rossi for helping me with the release! I can’t wait for Castle to move to GitHub so we can finally put that whole “non-committer sends patches” misery behind us.


It’s a kind of magic: MonoRail

October 21st, 2009 . by Daniel Hölbling

I never cease to be amazed about Castle MonoRail, but this time I was really puzzled.
While working on a simple CRUD page I wrote code like this:

public void Unlock([ARFetch("id")] Member member)
{
    PropertyBag["member"] = member;
}

public void Unlock([ARFetch("id")] Member member, DateTime expiration)
{
    ...

My view was then just a standard form, a textfield and a submit button.

<form action="" method="POST">
    <ul>
        <li>
            $FormHelper.LabelFor("expiration", "Account expiration date")
            $FormHelper.TextFieldValue("expiration", "29.01.2010")
        </li>
        <li>
            <input type="submit" value="Unlock" />
        </li>
    </ul>
</form>

And, you may have guessed it, I forgot to put a hidden field with the UserId in there somewhere!

Yes, I know – what a common mistake and what a bad one at that. But, and that’s the scary part. It worked still! I checked and re-checked, there is no Id anywhere passed as a result of the form submit, yet MonoRail somehow gets the Id from my previous call and works with that.

I couldn’t find the code inside MonoRail responsible for this behavior, and it seems only to work with Post requests to an empty action so far, but still amazing.

Well, since I can’t see the code, I remain skeptical and added the hidden id anyway. Witchcraft like this feels wrong, I like mysteries though.


Using ActiveRecord’s Field mapping to map custom enumeration classes

September 3rd, 2009 . by Daniel Hölbling

One thing that may be overlooked sometimes (I certainly did) is the ability of ActiveRecord to not only bind to properties but also to instance fields (yes, even private ones). This little feature came in very handy when I was looking for a way to persist a class based enumeration. I’ll tell you why in a minute.

First, I have Users that can be in one of 5 categories. None of which were important enough to warrant a foreign-key relationship modeling in the database, but I still wanted to encapsulate them in some sort of object to avoid doing string checking inside my code. The model looks like this:

image

I clearly didn’t want to have a Category table in my database, so I decided on creating the Category class while saving the Name property to the database.

Here is my implementation of the User.Category field:

[Field]
private string category;

public Category Category
{
    get { return Category.GetCategoryByName(category); }
    set { category = value.Name; }
}

As you can clearly see. My code is only dealing with Category objects (that can have implementations attached) while behind the scenes I only write the name of the category to the backing field. This way I get rid of magic strings inside my code while not having to burden my database with foreign key constraints.


How MonoRail selects it’s best ActionMethod candidate: CalculateParamPoints

August 27th, 2009 . by Daniel Hölbling

James Curran pointed me at one interesting flaw with my implementation of the DefaultValueAttribute for MonoRail I blogged about some weeks ago. This tipped me off to actually read the MonoRail code to find out how exactly MonoRail selects what overload of a ActionMethod to call.

MonoRail’s approach is as simple as it is brilliant, and reading the code that does this is a very pleasant experience. It took about 5 minutes to figure out the following:

If there are multiple public methods in a SmartDispatcherController that match the request’s action, MonoRail calculates a score of parameter points of each overload, picking the “heaviest” and executes it.
How that score is calculated is quite simple: Every matched parameter gets 10 points, unmatched 0.

But there’s more detail to this:

Every regular parameter (types not defining a attribute of IParameterBinder) where the parameter-name could be matched to the request parameter’s key, MR assumes assumes a weight of 10

In detail this means: Given the following ActionMethod with two parameters:

public void Test(string category, int page)
{    
}

Monorail will assign 10 points if the key “category” could be found in the server’s request object (Request["category"]) and another 10 if a parameter key called “page” is also present.

So the following call /Test.rails?category=beer&page=1 would account for 20 parameter points, whereas omitting page would result in only 10 points. MonoRail will then pick the method with the highest score of matched parameter points and call it with those parameters.

Now, obviously the following would lead to a disambiguation:

/Test.rails?category=beer

public void Test(string category, int page)
{    
}
public void Test(string category)
{
}

Category is present in both cases and page is unmatched, so both methods get 10 points and no useful distinction can be made. This is where MonoRail will award a bonus of 5 points to a method where all parameters could be matched. Thus giving Test(string) 15 points and Test(string, int) only 10, leading to the right match.

Now, in case of a parameter that is decorated with a IParameterBinder attribute (like ARFetch, DataBind etc) calculating those parameter points is delegated to the attribute class that then returns a score following it’s own logic (e.g.: if one attribute collects data from multiple request parameters it could return more than 10)

Let’s look at a sample implementation of CalculateParamPoints of the ARFetchAttribute:

public virtual int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
{
	String paramName = RequestParameterName ?? parameterInfo.Name;

	return context.Request.Params.Get(paramName) != null ? 10 : 0;
}

As you can see, ARFetch follows the usual MonoRail behavior and will return 10 in case it’s parameter-name could be matched, or 0 otherwise.

Still, all this doesn’t negate the fact that you could end up with ambiguities between action methods. In case many methods received the same number of parameter points MonoRail will simply call the first.

Oh, and did I mention that ASP.NET MVC can overload only on a per-http-verb basis? (Given that that’s a quite finite number of exactly 5)


Storing binary data in NHibernate / ActiveRecord

August 19th, 2009 . by Daniel Hölbling

I believe the simplest way to store binary data is to just put in the database. Whenever I’ve agreed to throw data to a disk I’ve had issues with deployment, administration or disaster recovery.

Simply put: Once you have a dependency from your database to your file system, you no longer have the luxury of only thinking about recovering the database. You now need to keep two pieces of your system “safe”, both requiring a completely different toolset than the other.

Besides the obvious second point of headache for backup/recovery, you also bring yourself into a world of hurt for deployment / maintenance scenarios.
Filesystem access rights can be a huge pain in the ass, and having to set them right (and keep them that way) is usually a time-bomb waiting to go off.

So, storing your binary data in the db solves many problems, but some new ones arise. Mostly implementation details, but I’d like to show you some things to keep in mind when writing binary data to db.

NHibernate supports no lazy loading of instance fields

image While with conventional ADO.NET I’d just put the binary data as a column inside the table it belongs to, NHibernate requires you to do things different. If you map your data like that NHibernate will fetch it whenever you read objects from that table, meaning that you’ll be querying large binary data fields for no reason, causing you application performance to significantly degrade over time.

 

What you want is to have NHibernate fetch that field only if it is accessed (lazy load it), and that’s not possible for fields inside a class, but it is possible for references. So your database schema should look like this:

image

And your mapping will look similar to this (I’ll use ActiveRecord for easier understanding):

[ActiveRecord]
public class Invoice : ActiveRecordBase<Invoice>
{
    [PrimaryKey]
    public int Id { get; set; }

    [BelongsTo(Lazy = FetchWhen.OnInvoke, Cascade = CascadeEnum.SaveUpdate)]
    public BinaryData ScannedInvoice { get; set; }
}

[ActiveRecord]
public class BinaryData : ActiveRecordBase<BinaryData>
{
    [PrimaryKey]
    public int Id { get; set; }

    [Property(ColumnType = "BinaryBlob", SqlType = "IMAGE", NotNull = true)]
    public byte[] Data { get; set; }
}

Now whenever your Invoice is saved/inserted NHibernate will also check if BinaryData has to be updated/inserted, while only loading the binary field if you actually access the Invoices.ScannedInvoice field.


DefaultValue attribute for Castle MonoRail

August 4th, 2009 . by Daniel Hölbling

While reading through ScottGu’s announcement of the ASP.NET MVC 2 Preview 1 I noticed this rather interesting little feature that’s in there:

DefaultValue attribute in ActionMethod

MonoRail is much smarter about action methods than MVC so there are already things going on with default values through routing etc. But this particular thing wasn’t in the framework until now. So I took Ken Egozi’s sample about using IParameterBinder to implement the DefaultValueAttribute in MonoRail.

The result in syntax is identical to ASP.NET MVC 2 P1 and it was very easy to do:

public void Browse([DefaultValue("beer")] string category, [DefaultValue(1)] int page)
{
    
}

How is this done? Well, I suggest you read Ken Egozi’s post since he does a much better job at explaining that thing. Anyway, here is the code to make that happen:

using System;
using System.Reflection;
using Castle.MonoRail.Framework;

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class DefaultValueAttribute : Attribute, IParameterBinder
{
	private readonly object value;
	public DefaultValueAttribute(object value)
	{
		this.value = value;
	}

	public int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
	{
		var token = context.Request[parameterInfo.Name];
		if (CanConvert(parameterInfo.ParameterType, token))
			return 10;
		return 0;
	}

	private static bool CanConvert(Type targetType, string token)
	{
		if (token == null)
			return false;

		try
		{
			Convert.ChangeType(token, targetType);
			return true;
		}
		catch (FormatException)
		{
			return false;
		}
	}

	public object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
	{
		string token = context.Request[parameterInfo.Name];
		Type type = parameterInfo.ParameterType;
		if (CanConvert(type, token))
			return Convert.ChangeType(token, type);
		return value;
	}
}

MVC vs MonoRail – Action Methods

July 31st, 2009 . by Daniel Hölbling

Many people have said nasty things about the Castle MonoRail framework since ASP.NET MVC has come out. Both serve the same purpose but both frameworks are pretty different. I did/do projects in both these days, and usually all features of A are also present in B, just slightly different.

One thing where this isn’t true is the layout of ActionMethods in MVC:

In short, MonoRail can have unlimited method overloads for ActionMethods while MVC can only overload twice (once for each HttpVerb).

What do I mean?

MVC:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(int id)
    {
        return View();
    }
}

MonoRail:

public class ContactController : SmartDispatcherController
{
    public void Index()
    {
        
    }

    public void Index(int id)
    {
        
    }

    public void Index(int id, string name)
    {
        
    }
}

You can see clearly, MonoRail as a framework is much smarter about what action method it will invoke. Based on what parameters you supply it will pick the best match. 
MVC will simply use reflection to invoke any method with that name that matches the HttpVerb, so once you remove the AcceptVerbs attribute MVC will break with a AmbiguousMatchException.

MVC vs MonoRail

Just to get bias out of the way: I believe MVC is technically still inferior to MonoRail but makes that up in larger community and (much) better documentation. What you pick is largely dependant on how well you know your way around missing documentation and open source code mailing lists.

To illustrate this I went to stackoverflow and compared the number of questions tagged with asp.net-mvc with those tagged castle-monorail. The results may very well speak for themselves:

image

It’s a shame I have to say. MonoRail is such a nice framework and it really does not deserve getting stomped by ASP.NET MVC. As funny as this may sound for a OSS project, currently the best way to contribute to MonoRail is to write about it and if possible improve documentation around it. I guess that says everything about the quality/maturity of the framework.


Keeping up with Castle binaries through NAnt

July 25th, 2009 . by Daniel Hölbling

One of the main annoyances of running from the castle trunk for me was copying new assemblies to my projects. Whenever I see something interesting pop up in the mailing list I usually run a SVN update to see what changed. While the castle build process is pretty simple at this point, picking the right assemblies and copying them to an ongoing project manually is just painful.

I did this exactly twice before I remembered the golden rule: automate!

This little NAnt target is now in charge of copying assemblies I need to my project’s lib directory:

<target name="castle-update">
<if test="${property::exists('castle-trunk-dir')}">

	<if test="${property::exists('skip-castle-compile') == false}">
		<echo message="Compiling castle trunk release binaries..." />
		<exec program="build.cmd" basedir="${castle-trunk-dir}" workingdir="${castle-trunk-dir}">
		</exec>
	</if>

	<echo message="copying castle binaries" />

	<copy todir="lib\castle">
		<fileset basedir="${castle-trunk-dir}\build\net-3.5\release\">
			<include name="Castle.ActiveRecord.???" />
			<include name="Castle.Components.Binder.???" />
			<include name="Castle.Components.Common.EmailSender.???" />
			<include name="Castle.Components.Common.TemplateEngine.???" />
			<include name="Castle.Components.Common.TemplateEngine.NVelocityTemplateEngine.???" />
			<include name="Castle.Components.DictionaryAdapter.???" />
			<include name="Castle.Components.Pagination.???" />
			<include name="Castle.Components.Validator.???" />
			<include name="Castle.Core.???" />
			<include name="Castle.DynamicProxy2.???" />
			<include name="Castle.MonoRail.ActiveRecordSupport.???" />
			<include name="Castle.MonoRail.Framework.???" />
			<include name="Castle.MonoRail.Framework.Views.NVelocity.???" />
			<include name="Castle.MonoRail.TestSupport.???" />
			<include name="Castle.Services.Logging.Log4netIntegration.???" />
			<include name="Iesi.Collections.???" />
			<include name="log4net.???" />
			<include name="*.license.txt" />
			<include name="NHibernate.ByteCode.Castle.???" />
			<include name="NHibernate.???" />
			<include name="NVelocity.???" />
		</fileset>
	</copy>
</if>
<if test="${property::exists('castle-trunk-dir') == false}">
	<fail message="Please specify the directory to castle-trunk through -D:castle-trunk-dir=<directory>" />
</if>
</target>

This little script will compile castle and then copy over all files I need to my /lib/castle folder, making a castle update as easy as writing:

build castle-update -D:castle-trunk-dir=..\open-source\castle-trunk

Make sure you have your /lib/ folder under source control in case some breaking changes come from the new castle binaries.


Keeping up with Castle

July 25th, 2009 . by Daniel Hölbling

Especially when trying to follow the development of a big project like Castle you can get lost quickly. There is no real “main” endpoint to refer to. Some news get out there through the development mailing list, sometimes they come through blogs and sometimes they are only present in code.

What I found useful in following the project are the following places:

  1. Castle Project aggregator – a aggregate feed of most known figures involved in the castle development process
  2. Castle Project development mailing list – The place where discussion about features and structure happens
  3. Castle Project svn log – I like to look at commits to see what’s going on
    Note: Especially with castle where the last “official” release was in 2007 it’s imo quite important to know what’s going on when you are running the trunk version.

FileUpload in MonoRail

July 24th, 2009 . by Daniel Hölbling

After a stressful week of non-computer related stuff eating up my time today I finally got around to continue some work on the imagineClub website.
I approached the section of file uploads and just wanted to quickly point out an excellent post by Ken Egozi about how to properly handle file uploads with MonoRail.

FileBinderAttribute to ease FileUpload in MonoRail – by Ken Egozi

It’s really nice to see that MonoRail has File upload baked directly into the framework. It’s as easy as that:

public void Upload([DataBind("Document")] Document document, HttpPostedFile uploadedFile)
{
	if (uploadedFile != null)
	{
		//TODO: Save File to Disk, Test this properly
	}
}

But what Ken addresses is a neat way to keep this testable without obscuring the controller code.

Also, apparently Ken has written his own weblog engine ontop of MonoRail and even opensourced it for the public to look at and hopefully learn something from it. It’s really great to see real application code somewhere instead of just samples and short demos. Also from what I saw in the repository it’s not too complex to make you cry and yet real enough to show you some interesting things about MonoRail.


« Previous Entries