<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-19588461</id><updated>2011-04-21T17:56:34.419-07:00</updated><title type='text'>MonoRail HowTo</title><subtitle type='html'>...my journey into the world of MVC web applications with the .NET Framework</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://monorail-howto.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://monorail-howto.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andre</name><uri>http://www.blogger.com/profile/15652895832262413722</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-19588461.post-113862823292715230</id><published>2006-01-30T05:36:00.000-08:00</published><updated>2006-01-30T05:37:12.950-08:00</updated><title type='text'>Blog Movin'</title><content type='html'>Moving my blog to &lt;a href="http://community.devpinoy.org/blogs/cruizer"&gt;DevPinoy&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19588461-113862823292715230?l=monorail-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://monorail-howto.blogspot.com/feeds/113862823292715230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19588461&amp;postID=113862823292715230' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113862823292715230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113862823292715230'/><link rel='alternate' type='text/html' href='http://monorail-howto.blogspot.com/2006/01/blog-movin.html' title='Blog Movin&apos;'/><author><name>Andre</name><uri>http://www.blogger.com/profile/15652895832262413722</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19588461.post-113391241809954247</id><published>2005-12-06T15:31:00.000-08:00</published><updated>2005-12-06T16:44:29.926-08:00</updated><title type='text'>Fun with ActiveRecord</title><content type='html'>Wow. &lt;a href="http://www.castleproject.org/index.php/ActiveRecord"&gt;ActiveRecord&lt;/a&gt; is fun :)&lt;br /&gt;&lt;br /&gt;It's still got some rough edges, but generally it really can speed up development. I haven't gotten around to using the ActiveRecord Generator software since I'd like to experience first-hand how to code this thing manually.&lt;br /&gt;&lt;br /&gt;Anyway just in case you don't know, ActiveRecord is an implementation of the &lt;a href="http://www.martinfowler.com/eaaCatalog/activeRecord.html"&gt;active record pattern&lt;/a&gt; documented by Martin Fowler in his book Patterns of Enterprise Application Architecture. It is actually a "port" of sorts from the &lt;a href="http://www.rubyonrails.com"&gt;Ruby on Rails&lt;/a&gt; Active Record implementation. Basically you have a class corresponding to a table, with each member/property corresponding to a field on that database table. The operations are either member or static methods. Well at least that's how it is implemented in Castle's ActiveRecord.&lt;br /&gt;&lt;br /&gt;So how does it hold up during actual development? At present ActiveRecord's documentation leaves a lot to be desired; it's somehow better to just peruse the examples provided in the download. I tried creating a MonoRail app that uses classes descended from ActiveRecord's ActiveRecordBase class and it sure was easy. I even did NUnit tests for it to make sure it really does what it's supposed to.&lt;br /&gt;&lt;br /&gt;Ok so where do I start? Let's take a simple table from a database. In my case I took a table called "usergroup" and I created a class named UserGroup. This class will be a subclass of ActiveRecordBase and will contain member properties corresponding to fields in the usergroup table. Here's how my UserGroup.cs code looks:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;using Castle.ActiveRecord;&lt;br /&gt;using NHibernate.Expression;&lt;br /&gt;&lt;br /&gt;namespace Testing.Model&lt;br /&gt;{&lt;br /&gt; [ActiveRecord("usergroup")]&lt;br /&gt; public class UserGroup : ActiveRecordBase&lt;br /&gt; {&lt;br /&gt;  private int _userGroupKey;&lt;br /&gt;  private string _userGroupName;&lt;br /&gt;  private string _userGroupType;&lt;br /&gt;  private string _description;&lt;br /&gt;  private string _eMailAddress;&lt;br /&gt;  private string _password;&lt;br /&gt;  private string _lastName;&lt;br /&gt;  private string _firstName;&lt;br /&gt;  private string _role;&lt;br /&gt;  &lt;br /&gt;  public UserGroup()&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [PrimaryKey(PrimaryKeyType.Native)]&lt;br /&gt;  public int UserGroupKey&lt;br /&gt;  {&lt;br /&gt;   get { return _userGroupKey; }&lt;br /&gt;   set { _userGroupKey = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string UserGroupName&lt;br /&gt;  {&lt;br /&gt;   get { return _userGroupName; }&lt;br /&gt;   set { _userGroupName = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string UserGroupType&lt;br /&gt;  {&lt;br /&gt;   get { return _userGroupType; }&lt;br /&gt;   set { _userGroupType = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string Description&lt;br /&gt;  {&lt;br /&gt;   get { return _description; }&lt;br /&gt;   set { _description = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string EMailAddress&lt;br /&gt;  {&lt;br /&gt;   get { return _eMailAddress; }&lt;br /&gt;   set { _eMailAddress = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [Property]&lt;br /&gt;  public string Password&lt;br /&gt;  {&lt;br /&gt;   get { return _password; }&lt;br /&gt;   set { _password = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string LastName&lt;br /&gt;  {&lt;br /&gt;   get { return _lastName; }&lt;br /&gt;   set { _lastName = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string FirstName&lt;br /&gt;  {&lt;br /&gt;   get { return _firstName; }&lt;br /&gt;   set { _firstName = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Property]&lt;br /&gt;  public string Role&lt;br /&gt;  {&lt;br /&gt;   get { return _role; }&lt;br /&gt;   set { _role = value; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public static UserGroup Find(int id)&lt;br /&gt;  {&lt;br /&gt;   return (UserGroup) ActiveRecordBase.FindByPrimaryKey(typeof(UserGroup), id);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public static UserGroup FindByName(string username)&lt;br /&gt;  {&lt;br /&gt;   UserGroup[] userArray = (UserGroup[]) ActiveRecordBase.FindAll(typeof(UserGroup), Expression.Eq("UserGroupName", username));&lt;br /&gt;   if (userArray != null) {&lt;br /&gt;    if (userArray.Length &amp;gt; 0) {&lt;br /&gt;     return userArray[0];&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   return null;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public static UserGroup[] FindAll()&lt;br /&gt;  {&lt;br /&gt;   return (UserGroup[]) ActiveRecordBase.FindAll(typeof(UserGroup));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As you can see it's got member properties and static methods Find(), FindByName() and FindAll(). ActiveRecord is actually a wrapper on top of &lt;a href="http://www.nhibernate.org"&gt;NHibernate&lt;/a&gt; so I made use of NHibernate's expression facility in the FindByName() method.&lt;br /&gt;&lt;br /&gt;With ActiveRecord, I can just instantiate the UserGroup class then Save() it to the database, or I can Update() or Delete(). It's pretty nifty. In my case I dropped that UserGroup.cs in my Testing\Models directory. Now on to the test class TestUserGroup.cs (in the Testing\Tests directory):&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;&lt;br /&gt;using NUnit.Framework;&lt;br /&gt;using Testing.Model;&lt;br /&gt;using Castle.ActiveRecord;&lt;br /&gt;using Castle.ActiveRecord.Framework.Config;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;&lt;br /&gt;namespace Testing.Tests&lt;br /&gt;{&lt;br /&gt; [TestFixture]&lt;br /&gt; public class TestUserGroup&lt;br /&gt; {&lt;br /&gt;  [SetUp]&lt;br /&gt;  public void SetUp()&lt;br /&gt;  {&lt;br /&gt;   ActiveRecordStarter.Initialize(new XmlConfigurationSource("../Tests/appconfig.xml"), typeof(UserGroup));  &lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Test]&lt;br /&gt;  public void TestCreate()&lt;br /&gt;  {&lt;br /&gt;   UserGroup user = new UserGroup();&lt;br /&gt;   Assert.IsNotNull(user);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Test]&lt;br /&gt;  public void TestFind()&lt;br /&gt;  {&lt;br /&gt;   UserGroup user = UserGroup.Find(1);&lt;br /&gt;   Assert.IsNotNull(user);&lt;br /&gt;   Assert.AreEqual("Admin", user.UserGroupName);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Test]&lt;br /&gt;  public void TestFindName()&lt;br /&gt;  {&lt;br /&gt;   UserGroup user = UserGroup.FindByName("Admin");&lt;br /&gt;   Assert.IsNotNull(user);&lt;br /&gt;   Assert.AreEqual("Admin", user.UserGroupName);&lt;br /&gt;   Console.WriteLine("name        = " + user.UserGroupName);&lt;br /&gt;   Console.WriteLine("description = " + user.Description);&lt;br /&gt;   Console.WriteLine("email       = " + user.EMailAddress);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Test]&lt;br /&gt;  public void TestSave()&lt;br /&gt;  {&lt;br /&gt;   UserGroup user = new UserGroup();&lt;br /&gt;   user.UserGroupName = "newuser";&lt;br /&gt;   user.UserGroupType = "U";&lt;br /&gt;   user.Description = "This is a new user";&lt;br /&gt;   user.EMailAddress = "myemail@gmail.com";&lt;br /&gt;   user.Save();&lt;br /&gt;   user = null;&lt;br /&gt;   user = UserGroup.FindByName("newuser");&lt;br /&gt;   Assert.IsNotNull(user);&lt;br /&gt;   Assert.AreEqual("newuser", user.UserGroupName);&lt;br /&gt;   user.Delete();&lt;br /&gt;   user = UserGroup.FindByName("newuser");&lt;br /&gt;   Assert.IsNull(user);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  [Test]&lt;br /&gt;  public void TestFindAll()&lt;br /&gt;  {&lt;br /&gt;   UserGroup[] users = UserGroup.FindAll();&lt;br /&gt;   Assert.IsNotNull(users);&lt;br /&gt;   Assert.IsTrue(users.Length &gt; 0);&lt;br /&gt;   Console.WriteLine("There are " + users.Length.ToString() + " users in the array.");&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Before I ran the test I prepopulated the UserGroup table with dummy data. It's referenced in the test code that I expect to Find() a record with a primary key (int) equal to 1. Anyway if you wish to run this code as well make sure you note that.&lt;br /&gt;&lt;br /&gt;Ok so what else are we missing...oh we require an appconfig.xml file as seen in the SetUp() method above! Ok so here goes:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;activerecord&amp;gt;&lt;br /&gt;  &amp;lt;config&amp;gt;&lt;br /&gt; &amp;lt;add &lt;br /&gt;  key="hibernate.connection.driver_class"  &lt;br /&gt;  value="NHibernate.Driver.OdbcDriver" /&amp;gt;&lt;br /&gt; &amp;lt;add &lt;br /&gt;  key="hibernate.dialect"      &lt;br /&gt;  value="NHibernate.Dialect.MsSql2000Dialect" /&amp;gt;&lt;br /&gt; &amp;lt;add &lt;br /&gt;  key="hibernate.connection.provider"   &lt;br /&gt;  value="NHibernate.Connection.DriverConnectionProvider" /&amp;gt;&lt;br /&gt; &amp;lt;add &lt;br /&gt;  key="hibernate.connection.connection_string" &lt;br /&gt;  value="DSN=myODBCDSN;UID=myUSER;PWD=myPASS;" /&amp;gt;&lt;br /&gt;  &amp;lt;/config&amp;gt;&lt;br /&gt;&amp;lt;/activerecord&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The appconfig.xml (of course you can name it whatever you want) is used by my test classes (in the Testing\Tests directory). Here you can see that we specified that the driver it uses in the ODBC driver. The particular dialect I wish to use is MS SQL Server 2000's dialect since that's the particular database I'm using. I also have the ODBC connection string there pointing to the System DSN named "myODBCDSN". The good thing with having a separate configuration for tests is that I can point my tests to a scratch database and the actual web application to a different database.&lt;br /&gt;&lt;br /&gt;Ok, so now I need to create my NAnt targets:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;target name="model" description="Testing model build"&amp;gt;&lt;br /&gt;  &amp;lt;csc target="library" output="${binDir}\Testing.Model.dll" debug="${debug}"&amp;gt;&lt;br /&gt;   &amp;lt;references&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\HashCodeProvider.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\Iesi.Collections.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\log4net.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\NHibernate.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\Castle.ActiveRecord.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\Castle.Model.dll" /&amp;gt;&lt;br /&gt;   &amp;lt;/references&amp;gt;&lt;br /&gt;   &amp;lt;sources basedir="${modelDir}"&amp;gt;&lt;br /&gt;    &amp;lt;include name="UserGroup.cs" /&amp;gt;&lt;br /&gt;   &amp;lt;/sources&amp;gt;&lt;br /&gt;  &amp;lt;/csc&amp;gt;&lt;br /&gt; &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In my case I have the DLL dependencies in the Testing\lib directory (defined in the NAnt property variable ${libDir}) and the data model classes in Testing\Models (defined in the property variable ${modelDir}). Note the six (!) DLLs required just to be able to come up with ActiveRecordBase-based classes. The output DLL is named Testing.Model.dll and is placed in the Testing\bin directory (variable ${binDir}).&lt;br /&gt;&lt;br /&gt;Now for the NUnit target:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;target name="modelTest" description="Testing model TDD" depends="model"&amp;gt;&lt;br /&gt;  &amp;lt;csc target="library" output="${binDir}\Testing.Tests.dll" debug="${debug}"&amp;gt;&lt;br /&gt;   &amp;lt;references&amp;gt;&lt;br /&gt;    &amp;lt;include name="${nunitDir}\NUnit.Framework.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${binDir}\Testing.Model.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\Castle.ActiveRecord.dll" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="${libDir}\Castle.Model.dll" /&amp;gt;&lt;br /&gt;   &amp;lt;/references&amp;gt;&lt;br /&gt;   &amp;lt;sources basedir="${testDir}"&amp;gt;&lt;br /&gt;    &amp;lt;include name="TestUserGroup.cs" /&amp;gt;&lt;br /&gt;    &amp;lt;include name="TestRegisteredUser.cs" /&amp;gt;&lt;br /&gt;   &amp;lt;/sources&amp;gt;&lt;br /&gt;  &amp;lt;/csc&amp;gt;&lt;br /&gt;  &amp;lt;nunit2&amp;gt;&lt;br /&gt;   &amp;lt;formatter type="Plain" /&amp;gt;&lt;br /&gt;   &amp;lt;test assemblyname="${binDir}\Testing.Tests.dll" /&amp;gt;&lt;br /&gt;  &amp;lt;/nunit2&amp;gt;&lt;br /&gt; &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Again, note the DLL dependencies. Finally I need to craft a .config file for the test classes. In my case it's named Testing.Tests.dll.config and it's expected to be found in the bin directory:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt; &amp;lt;configSections&amp;gt;&lt;br /&gt;  &amp;lt;section name="log4net"&lt;br /&gt;   type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /&amp;gt;&lt;br /&gt; &amp;lt;/configSections&amp;gt;&lt;br /&gt; &amp;lt;log4net&amp;gt;&lt;br /&gt;  &amp;lt;appender name="rollingFile" type="log4net.Appender.RollingFileAppender, log4net"&amp;gt;&lt;br /&gt;   &amp;lt;param name="File" value="log.txt" /&amp;gt;&lt;br /&gt;   &amp;lt;param name="AppendToFile" value="true" /&amp;gt;&lt;br /&gt;   &amp;lt;param name="RollingStyle" value="Date" /&amp;gt;&lt;br /&gt;   &amp;lt;param name="DatePattern" value="yyyy.MM.dd" /&amp;gt;&lt;br /&gt;   &amp;lt;param name="StaticLogFileName" value="true" /&amp;gt;&lt;br /&gt;   &amp;lt;layout type="log4net.Layout.PatternLayout, log4net"&amp;gt;&lt;br /&gt;    &amp;lt;param name="ConversionPattern" value="%d [%t] %-5p %c [%x] (%X{auth}) - %m%n" /&amp;gt;&lt;br /&gt;   &amp;lt;/layout&amp;gt;   &lt;br /&gt;  &amp;lt;/appender&amp;gt;&lt;br /&gt;  &amp;lt;root&amp;gt;&lt;br /&gt;   &amp;lt;priority value="ALL" /&amp;gt;&lt;br /&gt;   &amp;lt;appender-ref ref="rollingFile" /&amp;gt;&lt;br /&gt;  &amp;lt;/root&amp;gt;&lt;br /&gt; &amp;lt;/log4net&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The reason why I'm noting this is because for some reason I'm not familiar with, it insists on having a &lt;a href="http://logging.apache.org/log4net/"&gt;log4net&lt;/a&gt; section in the configuration file. Here I used the log4net appender RollingFileAppender. Anyway if you're not interested in viewing the log file produced by NHibernate through log4net, I suggest you just have a &amp;lt;log4net /&amp;gt; tag just to appease it.&lt;br /&gt;&lt;br /&gt;There! Now I can build my model class(es) using:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;D:\Testing&gt;nant model&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And test them using:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;pre&gt;D:\Testing&gt;nant modelTest&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As you can see in the test code, it's really easy to use ActiveRecord once you get past the configuration file stuff. :P What we did wasn't really test-driven development (since we did the UserGroup.cs code before we came up with the TestUserGroup.cs test class!) but in practice I create the model class first containing only properties and attributes, then I TDD the methods one by one. At least since the NAnt targets and configuration files are already in place, it's much easier to create new model classes, specify them in the NAnt "model" target, create a new test class for that model, specify it in the NAnt "modelTest" target then do the model methods TDD-style. Rinse, lather, repeat. :)&lt;br /&gt;&lt;br /&gt;Later I'll post about how I tied them into the controllers for the web application. You'll see first-hand how MonoRail really speeds up .NET web application development. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19588461-113391241809954247?l=monorail-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://monorail-howto.blogspot.com/feeds/113391241809954247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19588461&amp;postID=113391241809954247' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113391241809954247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113391241809954247'/><link rel='alternate' type='text/html' href='http://monorail-howto.blogspot.com/2005/12/fun-with-activerecord.html' title='Fun with ActiveRecord'/><author><name>Andre</name><uri>http://www.blogger.com/profile/15652895832262413722</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19588461.post-113386447910585587</id><published>2005-12-06T02:18:00.000-08:00</published><updated>2005-12-06T02:22:01.296-08:00</updated><title type='text'>It's not a roadblock</title><content type='html'>Thanks to the CastleProject mailing list, it was pointed out to me that prepending an exclamation mark (!) before a variable prevents the display of the variable name if the variable contains null. So instead of saying:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;code&gt;${user.LastName}&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I should be putting in:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;code&gt;$!{user.LastName}&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It was mentioned in the &lt;a href="http://jakarta.apache.org/velocity/docs/vtl-reference-guide.html"&gt;Velocity Template Language guide&lt;/a&gt;, which I overlooked :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19588461-113386447910585587?l=monorail-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://monorail-howto.blogspot.com/feeds/113386447910585587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19588461&amp;postID=113386447910585587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113386447910585587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113386447910585587'/><link rel='alternate' type='text/html' href='http://monorail-howto.blogspot.com/2005/12/its-not-roadblock.html' title='It&apos;s not a roadblock'/><author><name>Andre</name><uri>http://www.blogger.com/profile/15652895832262413722</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19588461.post-113385680810889106</id><published>2005-12-06T00:09:00.000-08:00</published><updated>2005-12-06T00:15:10.440-08:00</updated><title type='text'>Ugh, hit a roadblock...</title><content type='html'>I was already able to create ActiveRecord-based model classes and even test cases using &lt;a href="http://www.nunit.org"&gt;NUnit&lt;/a&gt;; however I hit a roadblock.&lt;br /&gt;&lt;br /&gt;I discovered that &lt;a href="http://nvelocity.sourceforge.net"&gt;NVelocity&lt;/a&gt; templates, if fed a null property or variable, renders the whole variable/property name (with dollar sign and all) in the HTML output instead of a (my expected) blank. Is this a feature, or a bug?&lt;br /&gt;&lt;br /&gt;I just don't find it acceptable to put in #set and #if template statements just to catch the null properties and render them as blanks...any input on this, people? Or is it time to edit the NVelocity source? :P&lt;br /&gt;&lt;br /&gt;Too bad...since I was just starting to discover the joys of coding skeletal controller classes and having a site structure up in record time...!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19588461-113385680810889106?l=monorail-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://monorail-howto.blogspot.com/feeds/113385680810889106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19588461&amp;postID=113385680810889106' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113385680810889106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113385680810889106'/><link rel='alternate' type='text/html' href='http://monorail-howto.blogspot.com/2005/12/ugh-hit-roadblock.html' title='Ugh, hit a roadblock...'/><author><name>Andre</name><uri>http://www.blogger.com/profile/15652895832262413722</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19588461.post-113377194558497601</id><published>2005-12-05T00:29:00.000-08:00</published><updated>2005-12-06T00:20:55.446-08:00</updated><title type='text'>MonoRail QuickStart</title><content type='html'>I find &lt;a href="http://www.castleproject.org/index.php/MonoRail"&gt;this project&lt;/a&gt; interesting. However the wiki seems to have outdated information and it was quite annoying to find inconsistencies between its documentation pages and the video demos (and even the downloadable files!). So I guess I'd like to help out by documenting my experience in starting out with MonoRail (and coming up with a skeleton/site template) through this simple blog. :)&lt;br /&gt;&lt;br /&gt;Warning though: I am no MonoRail expert;  I'm just starting out! The things I'll put in here are the stuff that worked for me, so if we have similar system configuration (WinXP SP2, NAnt 0.85) this might actually work for you.&lt;br /&gt;&lt;br /&gt;Anyway...first step for me was to download the &lt;a href="http://www.castleproject.org/downloads/MonoRail-Samples.zip"&gt;MonoRail-Samples.zip&lt;/a&gt; file. It's got a "SampleSite" directory. Just unzip it somewhere in your computer, we'll refer to it later.&lt;br /&gt;&lt;br /&gt;Next step is to create the web directory for development. I called my directory "Testing" and I put it somewhere in my computer. Now I create empty directories within the "Testing" directory:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;bin&lt;/li&gt;&lt;li&gt;Controllers&lt;/li&gt;&lt;li&gt;Models&lt;/li&gt;&lt;li&gt;Views&lt;/li&gt;&lt;/ul&gt;So far I've only used the bin, Controllers and Views directories. I'll make use of the Models directory as soon as I get to play with ActiveRecord. :)&lt;br /&gt;&lt;br /&gt;Remember the "SampleSite" sample? Copy the DLLs found in its bin directory (except for the SampleSite.dll file of course) to the Testing\bin directory.&lt;br /&gt;&lt;br /&gt;Now I'll also create a web.config file within the Testing directory:&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;lt;configSections&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;section name="monoRail"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;type="Castle.MonoRail.Engine.Configuration.MonoRailSectionHandler, Castle.MonoRail.Engine" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/configSections&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;lt;monoRail&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;controllers&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;assembly&amp;gt;Testing&amp;lt;/assembly&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/controllers&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;viewEngine viewPathRoot="Views"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;customEngine="Castle.MonoRail.Framework.Views.CompositeView.CompositeViewEngine, Castle.MonoRail.Framework.Views.CompositeView" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/monoRail&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;lt;system.web&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;httpHandlers&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;add verb="*" path="*.rails"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type="Castle.MonoRail.Engine.MonoRailHttpHandlerFactory, Castle.MonoRail.Engine" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;add verb="*" path="*.vm" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/httpHandlers&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/system.web&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and the sample Testing.build (NAnt) file:&lt;br /&gt;&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;project name="Testing" default="build" basedir="."&amp;gt;&lt;br /&gt;&amp;lt;description&amp;gt;Test MonoRail project&amp;lt;/description&amp;gt;&lt;br /&gt;&amp;lt;property name="debug" value="true" overwrite="false" /&amp;gt;&lt;br /&gt;&amp;lt;property name="myDir" value="." /&amp;gt;&lt;br /&gt;&amp;lt;property name="nunitDir" value="C:\nant\bin\lib\net\1.1" /&amp;gt;&lt;br /&gt;&amp;lt;property name="binDir" value="bin" /&amp;gt;&lt;br /&gt;&amp;lt;property name="controllerDir" value="Controllers" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="clean" description="remove output"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;delete&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;fileset&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\Testing.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/delete&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="build" description="Testing build"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;csc target="library" output="${binDir}\Testing.dll" debug="${debug}"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;references&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\Castle.MonoRail.Framework.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\Castle.MonoRail.Framework.Views.CompositeView.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\Castle.MonoRail.Framework.Views.NVelocity.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\Castle.MonoRail.Engine.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\Commons.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\log4net.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="${binDir}\NVelocity.dll" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/references&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;sources basedir="${controllerDir}"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;include name="HomeController.cs" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/sources&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/csc&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Note here that my NAnt distribution is in C:\NAnt and I'm using version 1.1 of the .NET Framework.&lt;br /&gt;&lt;br /&gt;Now that my build file is ready and so is my web.config, I code my simple controller (Testing\Controllers\HomeController.cs):&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// HomeController.cs&lt;br /&gt;using Castle.MonoRail.Framework;&lt;br /&gt;&lt;br /&gt;namespace Testing.Controllers&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;public class HomeController : Controller&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;public void Index()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;PropertyBag.Add("name", "User");&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;and view (Testing\Views\home\index.vm):&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;title&amp;gt;Testing&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;body&amp;gt;&lt;br /&gt; Welcome to MonoRail, ${name}&lt;br /&gt;&amp;nbsp;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now open up a command prompt window and unleash nant on the build file:&lt;br /&gt;&lt;div class="codeblock"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;D:\Testing&gt;nant&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So I end up with a Testing.dll file inside the Testing\bin directory. Final step is to open the IIS snap-in (Administrative Tools) and create a virtual directory pointing to the Testing directory. In addition I make sure I map the .rails extension to the aspnet_isapi.dll. Now the site should work :)&lt;br /&gt;&lt;br /&gt;Now we have a skeleton/framework and a working MonoRail web site. In the next couple of days I'll be posting my experience with doing the ActiveRecord pattern and using it in a real-world web app port :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19588461-113377194558497601?l=monorail-howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://monorail-howto.blogspot.com/feeds/113377194558497601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19588461&amp;postID=113377194558497601' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113377194558497601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19588461/posts/default/113377194558497601'/><link rel='alternate' type='text/html' href='http://monorail-howto.blogspot.com/2005/12/monorail-quickstart.html' title='MonoRail QuickStart'/><author><name>Andre</name><uri>http://www.blogger.com/profile/15652895832262413722</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
