Tigraine
Daniel Hoelbling talks about .NET

Bad poor man’s IoC in default MVC template

July 31st, 2009 . by Daniel Hölbling

This is directly from the standard MVC template upon starting a new project:

// This constructor is used by the MVC framework to instantiate the controller using
// the default forms authentication and membership providers.

public AccountController()
    : this(null, null)
{
}

// This constructor is not used by the MVC framework but is instead provided for ease
// of unit testing this type. See the comments at the end of this file for more
// information.
public AccountController(IFormsAuthentication formsAuth, IMembershipService service)
{
    FormsAuth = formsAuth ?? new FormsAuthenticationService();
    MembershipService = service ?? new AccountMembershipService();
}

I didn’t realize this is in the default template of ANY MVC install when Ayende pointed this out in his NerdDinner review yesterday. Wow, speaking of bad defaults..

If you don’t want to burden yourself with “real” IoC, at least do it right:

// This constructor is used by the MVC framework to instantiate the controller using
// the default forms authentication and membership providers.

public AccountController()
            : this(new FormsAuthenticationService(), new AccountMembershipService())
{
}

// This constructor is not used by the MVC framework but is instead provided for ease
// of unit testing this type. See the comments at the end of this file for more
// information.
public AccountController(IFormsAuthentication formsAuth, IMembershipService service)
{
    FormsAuth = formsAuth;
    MembershipService = service;
}

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.


SSL Errors can indicate wrong system time

July 28th, 2009 . by Daniel Hölbling

Imagine my face when I got the following screen while logging into Gmail in the morning:

image

Chrome really suggested that www.google.com has no valid SSL certificate and may be dangerous.
Also services like Windows Live Messenger and Windows Update refused to work due to broken SSL certificates.

Turns out, I accidentally set the system clock after a bios reset to 28. July 2008 instead of 2009. I guess I looked at the system time about 3 times before noticing the error :( .

Funny: The wrong year also prevented me from syncing the time with time.windows.com to get to the right one.


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.


Troublesome SQL Server 2008 installation

July 23rd, 2009 . by Daniel Hölbling

Since Visual Studio 2008 ships with a SQL Server Express 2005 installation I never really bothered to change that. All tools I work with support that and I never needed any of the 2008 specific features before.

Only, the current imagineClub Website is hosted on a SQL Server 2008 installation, so in order to access that database on my development machine I needed to install a 2008 version.
I figured it would be best to upgrade to Microsoft SQL Server 2008 Developer edition since I can get that for free through the imagineClub MSDN AA agreement so I downloaded the ISO and started the install, expecting the setup to figure out how to upgrade my current installation.

Unfortunately that is not possible. The SQL Server 2008 setup failed miserably and the setup is not automatically rolling back. That means that I ended up with a partial 2008 install and a partial 2005 install.
Most services were installed twice and neither would work.

Unfortunately the SQL Server Setup is just a collection of MSI files that get called in some weird order through the main setup routine. Therefore the errorlog of the main install just references other logfiles that should contain error-details, but skipping through an alien 30k logfile isn’t the easiest task.

I could finally complete the setup by running the uninstall on ALL things that contained SQL in their name on my machine, until only “Microsoft Sql Server 2008 (64-bit)” was left.

image

The main SQL Server 2008 entry then told me that apparently all parts of SQL Server 2008 are gone and it will remove itself from my programs list.

I then was able to re-run the standard installation and now I’m finally up and running with SQL Server 2008!

image

Apparently I was lucky to get away so easy. If the above isn’t working you could try to follow Mark Michaelis tips on how to get rid of SQl Server 2005/2008 manually.

Anyway, uninstall SQL Server 2005 Express before attempting to install a SQL Server 2008. Saves time in the long run!


ARFetch attribute in MonoRail

July 20th, 2009 . by Daniel Hölbling

MonoRail and ASP.NET MVC while being very different both almost mirror their features. Few things are impossible in one of both and the only really major difference between those two is that MonoRail comes packed with a suggested data access strategy: ActiveRecord.

This pre-packing is completely optional, it’s very easy to implement whatever data access logic you like, but if you choose ActiveRecord you’ll benefit from some nice things like the ARFetch attribute.

See this action method and judge for yourself:

public void Detail([ARFetch("Id")] NewsPost post)
{
    PropertyBag["post"] = post;
}

You just tell MonoRail through ARFetch what request-parameter is the object’s Id and it will fetch that entity from your DB and pass it into your method. It’s so simple that it’s almost tragic, yet it’s a huge time saver in most CRUD cases (edit, update and delete usually involve fetching the entity first).

Also, for a change, ARFetch is one of those few things inside MonoRail that needs zero documentation. It just works! (Besides the fact that you need to know it exists of course).


Windows Live Writer Plugin: Wrap code in <tt>

July 19th, 2009 . by Daniel Hölbling

As of late I try to mark code parts inside normal text with the <tt> tags to make them stand out as code. While writing my MonoRail tutorial yesterday I got really annoyed by switching between source and normal view inside Windows Live writer to add <tt> all over the place, so I figured I’d use the WLW Plugin API to write a plugin that wraps text inside <tt>.

namespace wlwWrapIn
{
    using System;
    using System.Windows.Forms;
    using WindowsLive.Writer.Api;

    [WriterPlugin("37CB2E7F-1809-4344-9527-526768A99E9F", "WrapInTT", PublisherUrl = "http://www.tigraine.at")]
    [InsertableContentSource("Wrap in <tt>", MenuText = "Wrap in <tt>", SidebarText = "Wrap in <tt>")]
    public class WlwWrapIn : ContentSource
    {
        public override System.Windows.Forms.DialogResult CreateContent(System.Windows.Forms.IWin32Window dialogOwner, ref string content)
        {
            content = String.Format("<tt>{0}</tt>", content);
            return DialogResult.OK;
        }
    }
}

Oh yeah it is that simple, just reference the WindowsLive.Writer.Api class and you can write a plugin like that.

In case someone needs my <tt> wrapping plugin, you can get it here: WrapInTT.dll


Building a databound contact form with MonoRail – Part 2: Sending Emails

July 18th, 2009 . by Daniel Hölbling

This is part 2 of a 3 part tutorial on writing a databound contact form with Castle Monorail that gets sent off by email. We already touched FormHelpers and DataBinding in Part1: Views and Databinding, now we’ll see how easy it is to send a email template with MonoRail.

The other parts of this tutorial:

Sending Emails

We left off with a Thanks controller method that gets a ContactRequest parameter and now should send off the data by email.

1 – Configuring our Servers

Anything involving emails usually requires a SMTP server. The same thing goes for MonoRail, yet MR will default the SMTPServer setting to 127.0.0.1 if you don’t explicitly configure it through your web.config. Unfortunately for me I don’t have a SMTP server sitting on my box, so I had to change that setting through the monorail configuration node inside our web.config:

<monorail smtpHost="smtp.server.com">
  <controllers>
	  <assembly>MonoRail.ContactForm</assembly>
  </controllers>
  .
  .

You can optionally also optionally configure smtpPort, smtpUsername and smtpPassword.

2 – Sending a sample Message

We’ll jump ahead a bit and send a email message right away to verify that our settings so far have been working. Sending emails is as simple as calling the DeliverEmail method from within our Thanks controller action:

public void Thanks([DataBind("FormData")] ContactRequest request)
{
    var message = new Message
                      {
                          To = "tigraine@tigraine.at",
                          From = "tigraine@tigraine.at",
                          Subject = "Hello World",
                          Body = "My first message"
                      };
    DeliverEmail(message);
}

It’s really that easy.

3 – Templating the Message

It’s simple to send emails as seen in step 2, but having to chop strings together to send emails is just awful and error prone. Especially when you want some fancy HTML layout in your emails you’ll want to leverage the power of your ViewEngine to create the email message.

MonoRail provides such a method with it’s RenderMailMessage method. RenderMailMessage takes in a viewname, a layout and a IDictionary of parameters that will get passed on to the view.

For this simple tutorial I chose not to use a layout, so I pass in null. Also make sure you cast your Dictionary to the non-generic IDictionary since there is a little bug with the generic IDictionary overload.

public void Thanks([DataBind("FormData")] ContactRequest request)
{
    var parameters = new Dictionary<string, object>{{"request", request}};
    var message = RenderMailMessage("contact", null, (IDictionary)parameters);
    DeliverEmail(message);
}

MonoRail will look for email-templates inside the Views\mail\ folder, so we’ll add our contact.vm there:

image One thing you’ll notice immediately is that all information about from, to, subject and body have not disappeared from our action method. This data will now get extracted from the view, allowing for easy customization.

To do so we need our view to look like this:

to: tigraine@tigraine.at
from: $request.Email
subject: $request.Subject

This is where the body starts
Message from $request.Name

$request.Text

MonoRail will extract the information from the to: from: fields and use them to send the message. The above also uses the parameters we passed in to render. $request here refers to the object passed into our dictionary with name request.

If run we’ll end up with a email simiar to this:

image

4 – Testing it

Email interactions are perfect examples of stuff that goes wrong without anyone noticing. Someone does some changes in the controller and all of a sudden you don’t get those annoying contact requests for a week. Usually you blame it on a slow week and by the time you suspect something is wrong you already ignored a month of customer feedback.

To avoid this we’ll want to unit test this, and while I usually write my tests first – it’s easier to follow if you know the code under test. Testing in MonoRail is quite simple once you know where to look, unfortunately the documentation is scattered and scarce.

We’ll begin by making our testclass derive from BaseControllerTest, a class inside the Castle.MonoRail.TestSupport assembly that is used to facilitate testing.

public class ContactBehaviorTest : BaseControllerTest
{
    
}

This provides us with a neat little function that allows us to sandbox our controller called PrepareController.

Testing that a message has been rendered through the template engine would therefore look like this:

[Fact]
public void Thanks_RendersTemplatedEmail()
{
    var controller = new ContactController();
    PrepareController(controller);

    controller.Thanks(null);

    Assert.True(HasRenderedEmailTemplateNamed("contact"));
}

This test merely verifies that a template was rendered, but we probably want to verify that the view gets passed the correct arguments:

[Fact]
public void Thanks_MailRendering_ParametersGetPassed()
{
    var controller = new ContactController();
    PrepareController(controller);

    var request = new ContactRequest();
    controller.Thanks(request);

    var parameters = RenderedEmailTemplates[0].Parameters["request"];
    Assert.Same(request, parameters);
}

We now have verified that the “request” parameter object is indeed the one passed into the action method. This is not perfect since we’d just want to verify that the correct values get passed around, not references. But for this tutorial this will suffice.

Next on our checklist should be the fact that the created message is indeed sent off. We do so by using the StubEngineContext our BaseControllerTest provides us with:

[Fact]
public void Thanks_EmailSending_SendsOutOneEmail()
{
    var controller = new ContactController();
    PrepareController(controller);
    var context = (StubEngineContext)Context;

    controller.Thanks(new ContactRequest());

    Assert.Equal(1, context.MessagesSent.Count);
}

This now simply verifies that we did indeed send a mail message.

Now we have a fully working contact form that gets sent off by email through a template. We may want to protect that form from bad input by validating some of our fields. Check back tomorrow for part 3 of this tutorial.

Ps: As always the source for this tutorial is available in my BitBucket samples repository. Usually one changeset represents one tutorial step.


« Previous Entries