Tigraine

Daniel Hoelbling-Inzko talks about programming

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

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 = "[email protected]",
                          From = "[email protected]",
                          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: [email protected]
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.

Filed under net, castle, programmierung

ActiveRecord gotchas when testing with an in memory database.

If the title sounds familiar to you, it’s intentional. After having to deal with this in pure NHibernate it came around to also bite me with ActiveRecord.

In short: in-memory SQLite will drop the schema whenever you close the NHibernate ISession object (since ActiveRecord uses NHibernate behind the scenes this poses a problem to us).

So, assuming you have setup ActiveRecord using an InPlaceConfiguratonSource similar to this:

IDictionary<string, string> properties = new Dictionary<string, string>();
properties.Add("connection.driver_class", "NHibernate.Driver.SQLite20Driver");
properties.Add("dialect", "NHibernate.Dialect.SQLiteDialect");
properties.Add("connection.provider",                "NHibernate.Connection.DriverConnectionProvider");
properties.Add("connection.connection_string", "Data Source=:memory:;Version=3;New=True;");
properties.Add("show_sql", "true");
properties.Add("proxyfactory.factory_class",                "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");

var source = new InPlaceConfigurationSource(); source.Add(typeof (ActiveRecordBase), properties);

ActiveRecordStarter.Initialize(source, typeof (Member).Assembly.GetTypes()); ActiveRecordStarter.CreateSchema();

You will not be able to run any queries against it because there is no schema present. In fact the code will consistently blow up with a SQLiteException stating “no such table: ….”. Unfortunately it’s not really possible to change the SessionFactory implementation here because that code is inside ActiveRecord.

Thank god I found this handy guide that suggested subclassing the DriverConnectionProvider class to replace the CloseConnection call with a fake like this:

public class SqLiteInMemoryTestingConnectionProvider : NHibernate.Connection.DriverConnectionProvider
{     public static System.Data.IDbConnection Connection = null;     public override System.Data.IDbConnection GetConnection()     {         if (Connection == null)             Connection = base.GetConnection();         return Connection;     }     public override void CloseConnection(System.Data.IDbConnection conn)     {     }
}

I then had to pass that new ConnectionProvider into NH through the configuration and all was well:

properties.Add("connection.provider",                "ImagineClub.Tests.SqLiteInMemoryTestingConnectionProvider, ImagineClub.Tests");

Only catch is, this doing the AR Initialization is painfully slow so I wrote a baseclass for my xUnit tests that makes sure AR Init is only run once and that the ActiveRecordStarter.CreateSchema() is run before every test (xUnit runs the testclass constructor before each test):

The final implementation for all my tests looks like this:

public class ActiveRecordInMemoryTestBase
{     public ActiveRecordInMemoryTestBase()     {         if (!ActiveRecordStarter.IsInitialized)             Initialize();         ActiveRecordStarter.CreateSchema();     }     private static void Initialize()     {         IDictionary<string, string> properties = new Dictionary<string, string>();         properties.Add("connection.driver_class", "NHibernate.Driver.SQLite20Driver");         properties.Add("dialect", "NHibernate.Dialect.SQLiteDialect");         properties.Add("connection.provider",                        "ImagineClub.Tests.SqLiteInMemoryTestingConnectionProvider, ImagineClub.Tests");         properties.Add("connection.connection_string", "Data Source=:memory:;Version=3;New=True;");         properties.Add("show_sql", "true");         properties.Add("proxyfactory.factory_class",                        "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");         var source = new InPlaceConfigurationSource();         source.Add(typeof (ActiveRecordBase), properties);         ActiveRecordStarter.Initialize(source, typeof (Member).Assembly.GetTypes());         ActiveRecordStarter.CreateSchema();     }
}

public class SqLiteInMemoryTestingConnectionProvider : NHibernate.Connection.DriverConnectionProvider {     public static System.Data.IDbConnection Connection = null;     public override System.Data.IDbConnection GetConnection()     {         if (Connection == null)             Connection = base.GetConnection();         return Connection;     }     public override void CloseConnection(System.Data.IDbConnection conn)     {     } }

Caution: If you copy/paste the above make sure to change the namespace and assemblyname for your SqLiteInMemoryTestingConnectionProvider to match yours.

So a database dependant unit test would look like this:

public class DatabaseTest : ActiveRecordInMemoryTestBase
{     [Fact]     public void DatabaseIsEmpty()     {         Assert.Equal(0, Member.FindAll().Length);     }
}

Initial runs are quite slow due to the AR Init, but the whole test-suite should run quite fast since only the schema creation is run before each test.

Dropping IE6

This one’s going to be quick. While doing the xhtml/css for the new iC-Website I decided that there will be no IE6 support. The site will be standards compliant and should pass W3C XHTML 1.0 strict validation.

The current markup already works quite well with absolutely no hacks/js-tricks to look like this:

image

Since IE8 renders this flawlessly (except for the rounded corners within the date), I see no real value in trying to make this check out in IE6. I’ve spent too much time on this already so in case you haven’t upgraded yet: Get IE8!

On a side note: I’m amazed how well IE8 renders the site. Everything I did so far worked perfectly on all 3 rendering engines without any problem. Thank god the dark days are over!

As always, you can follow the development on BitBucket. The site’s source code is available there. Feel free to comment on the markup :).

Making simple things hard: NVelocity

I was pretty done with the world after spending almost 2 days with xhtml/css coding for the new iC-Website. Turns out the programming gods want to teach me a lesson. Look at my Google Search log:

image

What you see here is me spending almost 45 minutes on formatting a date!

I need to take the date and split it into 3 parts so I can stick it into the following markup:

<div class="date">
    <span class="day">$day</span><span class="month">$month</span>
    <hr />
    <span class="year">$year</span>
</div>

I thought, hey that should be really simple, just call DateTime.ToString() and all will be well. And because it was so obvious I tried to create a macro to keep my viewcode clean. The result was:

#macro ( dateBox $currentDate )
#set ($day = $currentDate.Day.ToString("00") )
#set ($month = $currentDate.Month.ToString("00") )
#set ($year = $currentDate.ToString("yy") )
<div class="date">
    <span class="day">$day</span><span class="month">$month</span>
    <hr />
    <span class="year">$year</span>
</div>
#end

I still have no explanation why passing a DateTime into the macro isn’t working. Maybe because calling macros in NV isn’t the same as calling a CLR method. So I had to abandon the macro idea and just code it the way it is.

Now what really pissed me off to the point where I almost considered using ASPView as a view engine was that I spent almost 45 minutes with this for one simple reason: NVelocity won’t report errors as long as they don’t break the parser.

Perfect example:

$DateTime.Now.Format("dd MM yyyy")

Will just result in a “$DateTime.Now.Format("dd MM yyyy")” output, for no apparent reason other than the fact that there is no Format() method on the DateTime. Clearly my bad, I’m stupid and far too dependent on IntelliSense, but if NV isn’t telling me how I screwed up it’s really hard to find the mistake. Especially without syntax highlighting and intellisense DateTime.Format(…) looks perfectly reasonable at first.

Finally I ended up with this:

#set ($day = $currentDate.ToString("dd") )
#set ($month = $currentDate.ToString("MM") )
#set ($year = $currentDate.ToString("yy") )
<div class="date">
    <span class="day">$day</span><span class="month">$month</span>
    <hr />
    <span class="year">$year</span>
</div>

Filed under net, castle, programmierung

Mixing static strings with NVelocity variables

In an ongoing effort to get into NVelocity while programming the iC-Website I wanted to concatenate a filename with the current loop count variable:

<img src="/Content/images/dummy$velocityCount.png" alt="post-image" />

This isn’t working. You’ll end up with dummy$velocityCount.png. While I’d like it to result in dummy1.png.


I suspected it could be solved somehow by using our beloved angle bracket to tell NV to explicitly evaluate my text:

<img src="/Content/images/dummy{$velocityCount}.png" alt="post-image" />

This will result is dummy{1}.png, why is beyond me but NV will parse it. Still this doesn’t really work so I found the solution on how to explicitly invoke NV evaluation in the NV users guide:

<img src="/Content/images/dummy${velocityCount}.png" alt="post-image" />

This is nothing really new, it’s all laid out in the NV users-guide, still especially the second case made me scratch my head for a moment.

Filed under net, programmierung

IT-Camp 2009 at Klagenfurt University

© Georg Holzer

Ever tried mixing 9 high school students, XNA Game Studio 3.1 and one week of mentorship together? The result is nondeterministic, but experience showed that the projects turn out to be really awesome and fun to build.

After last year’s IT-Camp the University of Klagenfurt decided to continue the project where 15-17 year old teenagers are brought to Klagenfurt to experience university life firsthand. Like last year I was instructing a course about computer game development using Microsoft XNA Game Studio together with Christoph Kofler.

The first day started with a short introduction to computer games in terms of genres, target audience and distinctions. Turns out most of our students were avid players, so we couldn’t keep them away from our Guitar Hero setup for long. After Christoph and I got our asses kicked at Guitar Hero we then went on to analyze what made games great or not and how to judge games in different genres.

On Tuesday Mathias came in to deliver a little lecture about game design (thank again!) before we gave them a little tutorial on XNA and the most important things in 2D space like collision detection and state management. After that, they started development of their own games.

Game projects where pretty diverse this year since we explicitly allowed them to experiment with their own ideas rather than everyone doing the same 2D space shooter. This led to these really awesome projects:

Fisch-Game:

The little fish Kiku has to save the mermaid. He has to avoid the sharks for more than 40 seconds to finish the game. Complete with Arielle the mermaid sounds.

Adventure

A

This Zelda-like adventure features a scrolling map and animated characters. A per pixel collision detection was also implemented. Goal is to solve one simple quest, but the whole thing could easily be extended to something much bigger.

Mario-Clone

A Supermario clone that features basic collision detection and shooting of a projectile. The projectile will only hit one enemy and different enemies do more or less damage. Also it uses a small state machine to allow Mario to jump and fall.

Maxrace

A fairly simple but funny game. Goal is to reach the princess by alternating the left and right arrow button on the keyboard. Time is recorded and entered into the highscore. Really cool about this game is it’s simplicity in state – only one variable is incremented by 1 every valid keystroke.

Asteroidsx

A Asteroid clone that features a physics engine. Asteroids get drawn into the planet in the middle by gravity, player has to avoid asteroids and "poke" them if they are too far away from the planet's gravity to keep them going. Very challenging math-wise and well implemented. Unfortunately features were cut because of delays on the physics part.

Presentation

This was the first chance I had to try out a more “amateurish” style of PowerPoint slides that led to me buying a graphic tablet. The presentation was quite successful I think, so we used the same one for the final presentation before media and parents:

Finally

I’d really like to thank the University of Klagenfurt and Mathias Lux for this opportunity and also say a little thanks to our students. The week was (as last year) a very rewarding and fun experience for me and I hope to continue this next year.

After 2 years of doing this with XNA game studio I’d also like to point out that XNA has proven itself to be a really perfect tool for starting game development. We get students with a quite diverse skill set and they all picked up the tool very easily and all managed to deliver something truly awesome, whether it was object-oriented or just a long procedural piece. The framework won’t stand in your way while still giving you some of the most important stuff for free.

Sourcecode

The Sources of the games will be hosted at the IT-Camp’s website and I’ll add a link to it as soon as we manage to upload it.

Ps: Thanks Georg Holzer for allowing me to use his photograph of our end presentation!

Filed under programmierung, personal

imagineClub Website feedback results

I hate web development, I learned to hate it when I was translating Photoshop designs into XHTML years ago and I was really hoping to never do it again.

Unfortunately, most people who took the iC Website design survey really liked the new design, so I decided to start working to get this thing done sometime soon. Here is the poll result:

image

Thanks again to all who participated!

So, where are we? First: I am developing the iC website in the open. The source code is available at the project’s BitBucket site, so if you want to see what progress has been made just follow the project’s commit history RSS.

Sadly, Currently the repository is more or less a blank MonoRail template while I am trying to get the XHTML to look like Kristof’s design. I am really trying hard to maintain a clean markup to enable accessibility to all users.

Unfortunately, my CSS skills are somewhat lacking, so I had to learn the hard way that background-position won’t work with background-repeat, and that there is no chance in hell we’ll ever support IE6.

I’m also not sure yet on what license the project should use. I slashed a APL2 license on it just to have one, but I guess we’ll drop that in favor of a CC license.

My new toy: Wacom Bamboo

After almost two weeks of waiting for it I finally picked up my Wacom Bamboo today.

So, here comes the obvious for a programmer:

image

So, I got myself a pen tablet. Why would I do something like that?

First: Rest assured, I didn’t jump on the designer bandwagon, I still suck at drawing and that Hello World up there took me 3 tries and still looks bad.

It just happened that I loved Jon Skeet’s presentation slides he had for the OS Jam at Google London on C# 4 and DLR. The idea is just brilliant. Almost no real content on the slides, just some pointers in a very “human” style.

While I was preparing for this years summer-camp at the University (I’m instructing some kids on XNA game programming again) I used a CintiQ 21UX we have sitting at the company to try this with some pretty cool results:

image

image

Obviously, a bunch of 16 year olds isn’t the perfect gauge for presentation slides, but almost everyone who saw that slide deck loved it. It’s so totally different and less formal and tense that it was totally worth the work. I just didn’t want to make a habit out of using other people’s PCs at work so I obviously needed something similar, yet much cheaper. And that’s where the Bamboo A6 really came in handy: 70€ at my local DiTech store was quite a bargain. (Although it took them 2 weeks to order and deliver that thing!)

On the Bamboo side of things, it just works. You plug it in and it works. After installing the driver I had around 30 minutes of trouble finding the settings dialog to make the tablet not target my whole screen (A6 pointing at a 24” screen is just awful), but once I reduced that it became a joy to work with. Recognition is very sharp and very precise, the different pressure levels are nice in Photoshop.

I’m also amazed about how well the Windows Vista handwriting recognition has become. Obviously as a programmer I’m still a thousand times faster when using the keyboard, but it’s nice see it working.

Another application besides presentations is obviously my blog. I hate UML modeling software with all my heart. So much that my drafts folder has accumulated 3 different rants about how clumsy and slow it is to throw together a UML with the current tools. I usually end up writing code to generate a class diagram instead of trying to model a class without coding it.
With the power of a tablet I can just throw together a raw sketch out the UML to illustrate my point without having to jump through all the hoops current modeling software puts you through. So in the future, expect some of these:

image 

Btw: Thanks for all the feedback on the iC-Website design (if you didn’t already vote, please tell us what you think)!

Filed under programmierung, personal, tools

New office feels liberating &ndash; outside is still better

It’s been kind of a slow week for me in programming, but I made up for it in renovating my office and learning new stuff! I managed to get hold of some really nice office furniture so decided it’s time to repaint and throw out the old crap I’ve been sitting at for years.

Sadly I don’t have a before-shot of what my setup used to look like, but it was basically a combination of two tiny desks (one actually being a very old dressing table), one holding my screen and the other hosting keyboard and mouse. While it worked for many years, especially when working with paper it was very uncomfortable since there was hardly any space left besides keyboard and mouse. Also, I have to admit it always felt very cramped since the desk was hardly bigger than the chair I’m sitting in.

So, this is how awesome it looks now:

The old furniture was dark wood and the walls needed new paint pretty badly, so by repainting and putting in bright furniture the whole room has lit up. Everything feels bigger and less depressing :).

The new setup allows me to easily switch between my PC and the little workspace on the right (where I plan to have my laptop sitting mostly) and also makes room for a second screen I’ve been planning on buying for quite some time now.

Now, the only problem that remains is cooling. Without air conditioning I frequently get temperature to rise above 30°, making work during the day almost unbearable. 3 computers generate a lot of heat in a small room, and the big screen doesn’t really help either. Unfortunately having AC setup is nearly impossible without breaking the wall’s insulation so I’ll have to abandon base during the hot hours:

This picture is taken from a very nice little cafe at Wörthersee called Schamandra. They have good ice cream and really nice coffee and view. Unfortunately there is no free wifi, but 3G reception is very good. Another place I love to go to when in need of piece and quiet is Unterkreuth. A very nice bar on the top of a mountain usually frequented by paragliding enthusiasts, since they started serving coffee there is really no better place to be.

Both places are easily reachable from Klagenfurt in 10-15 minutes by car and provide exactly the piece and quiet I require when I need to watch a screencast or read a book.

Ps: I’d like to thank Robert for lending me his superhuman strength for two days and making the new office happen.

Filed under personal

Using ELMAH Error logging with Castle MonoRail Rescues

On my last project I made ELMAH (the ever awesome ASP.NET error logging framework) work with ASP.NET MVC by modifying the routing logic a bit. It was quite simple since ASP.NET MVC throws HttpExceptions around quite liberally and you are frequently presented with a YSOD that then gets logged by ELMAH.

Using MonoRail the general routine of setting up ELMAH still applies (even simpler), but it’s customary to have a general rescue view that informs the user when something went wrong. Since the rescue concept in MR basically swallows Exceptions and prevents them from reaching ELMAH we need to serve them to ELMAH through ErrorSignaling.

Defining a rescue in MonoRail according to the tutorials looks like this:

[Rescue("generalError")]
public class DemoController : SmartDispatcherController
{
    [Rescue("indexError")]
    public void Index()
    {
        throw new DivideByZeroException();
    }
}

The string passed to the RescueAttribute identifies the name of the view to load within your Views\rescues\ folder if an exception occurs. This is bad for us because we can’t execute any code to signal ELMAH on the way to the view and within the view.

This is where the RescueController overload for RescueAttribute comes into play. You can define a whole controller that will handle exceptions and we can execute code there before rendering a view. To do so we just need to implement IRescueController and inherit from SmartDispatcherController:

[Layout("default")]
public class RescueController : SmartDispatcherController, IRescueController
{
    public void Rescue(Exception exception, IController controller, IControllerContext controllerContext)
    {
        ErrorSignal.FromCurrentContext().Raise(exception);
        RenderSharedView(Path.Combine("rescues", "generalerror"));
    }
}

We can use this new controller by changing the Rescue attribute:

[Rescue(typeof(RescueController))]
public void Index()
{
    throw new DivideByZeroException();
}

Now in case you want to have multiple error-pages (like one general and one telling the user he did something wrong) you could also define multiple rescue methods inside your RescueController and call each of those when needed:

[Rescue(typeof(RescueController))]
public class DemoController : SmartDispatcherController
{
    [Rescue(typeof(RescueController), "IndexRescue")]
    public void Index()
    {
        throw new DivideByZeroException();
    }

    public void List()     {         throw new NotImplementedException();     } }

If an exception was to occur in List() it would get handled by the Rescue method inside your RescueController, if Index throws MR will try to call a method called IndexRescue. And both can be logged by ELMAH.

My Photography business

Projects

dynamic css for .NET

Archives

more