Browse by Tags

All Tags » MonoRail (RSS)

Enabling Windsor Integration in MonoRail

I recently wanted to take on old MonoRail application and update it to use Windsor for dependency injection (DI).  The application stated as a sort of prototype and slowing grew into a decent sized application.  There's a couple of places that I want to add some unit tests and I could really benefit from DI.  So I sat down to hook Windsor into the application. There's already documentation on how to integrate Windsor into MonoRail .  After all, they kind of "grew up" together.  However, the documentation is a little old and MonoRail has gone through a number of changes (some breaking) and improvements.  The " using MonoRail " site (a sort of wiki-like site) had some information on integrating Windsor into MonoRail which was more up-to-date than the Castle docs, but still left out an important section about ViewComponents.  So I thought I'd bring everything I learned into a single blog post.  I plan to take much of this and use it to update the Castle docs as well as the "using" site. Requirements You'll need to reference a few extra assemblies in your MonoRail application: Castle.DynamicProxy2.dll Castle.MicroKernel.dll Castle.Windor.dll Castle.MonoRail.WindsorExtension.dll Custom Container The first thing is to create a sub-class of the Windsor container for your MonoRail application.  This specialized version of the container will add the following capabilities: It will add a new facility which will automatically configure our Controllers for a transient lifestyle (one instance per request).  Windsor's default lifestyle is Singleton (imagine having only a single instance for each controller – yikes!!). It will automatically register all of our controllers for us.  This is optional as you can individually register each controller, but I find the automatic registration much easier. It will automatically register all of our ViewComponents .  Like controllers, this could be done individually, but this is easier. Our custom container is really quite simple.  We'll create WebAppContainer.cs in our App_Code directory.  Our constructor will call the base class constructor that will initialize the container from the config file (web.config): using Castle.Core.Resource; using Castle.Windsor.Configuration.Interpreters; using Castle.MonoRail.WindsorExtension; using Castle.Windsor; using Castle.MicroKernel.Registration; using Castle.MonoRail.Framework; using Castle.Core;   public class WebAppContainer : WindsorContainer { public WebAppContainer() : base ( new XmlInterpreter( new ConfigResource())) { }   public void Init() { } } Now let's work on our 3 items above.  We'll plug all of this into our Init() method which we'll call later when we initialize our container. First, we add a facility for MonoRail integration.  This facility is part of MonoRail: AddFacility( "rails" , new MonoRailFacility()); Next, we register all of our controllers (yes, in one statement).  My controllers are in a separate assembly so this is how my registration looks: Register( AllTypes.Of<IController>() .FromAssemblyNamed( "YourAssemblyName.Controllers" )); If your controllers are directly in your web application, you can change "FromAssemblyNamed(…)" to "FromAssembly(Assembly.GetExecutingAssembly())". Now we also need to register our ViewComponents.  This registration will also make sure that the ViewComponents are set up with a transient lifestyle: Register( AllTypes.Of<ViewComponent>() .FromAssemblyNamed( "YourAssemblyName.Controllers" ) .Configure(cr => cr.Named(cr.ServiceType.Name).LifeStyle.Is(LifestyleType.Transient)) ); That's it for the container!  Our complete, customized container looks like this: using Castle.Core.Resource; using Castle.Windsor.Configuration.Interpreters; using Castle.MonoRail.WindsorExtension; using Castle.Windsor; using Castle.MicroKernel.Registration; using Castle.MonoRail.Framework; using Castle.Core;   public class WebAppContainer : WindsorContainer { public WebAppContainer() : base ( new XmlInterpreter( new ConfigResource())) { }   public void Init() { AddFacility( "rails" , new MonoRailFacility());   Register( AllTypes.Of<IController>() .FromAssemblyNamed( "YourAssemblyName.Controllers" ));   Register( AllTypes.Of<ViewComponent>() .FromAssemblyNamed( "YourAssemblyName.Controllers" ) .Configure(cr => cr.Named(cr.ServiceType.Name).LifeStyle.Is(LifestyleType.Transient)) ); } } Integrating Our Container Now we need to hook this container into our web application.  We need to plug this into our custom HttpApplication (usually, your GlobalApplication.cs).  First, we need to add the IContainerAccessor interface: public class GlobalApplication : HttpApplication, IContainerAccessor Now add a static class variable...

Ajax Survey

From BradA : Simone Chiaretta is doing another Ajax survey to see how things have changed since his last survey a couple of years ago.  I just filled it out (you should too!).  The survey can be found here . Oh, and if the suspense is killing you, I'll give you my answers: I'm using AJAX in a production application. It's part of a MonoRail application. I'm using the Prototype on the client. Technorati Tags: Ajax , Survey , MonoRail
Posted by Patrick Steele's .NET Blog
Filed under: , , ,

OutputDebugStringAppender in a web app?

I spent a couple of hours yesterday trying to get log4net to log to an OutputDebugStringAppender with no success.  At first, I thought I had a configuration error in log4net so I added a file appender and that works fine.  It's a Monorail application that uses ActiveRecord for database access.  There's a couple of spots where I wanted to check out the SQL being generated by ActiveRecord (NHibernate).  I did all my set up for log4net and even got it logging to a FileAppender.  But I wanted to log the SQL to an OutputDebugStringAppender. Here's my logging set up: 1: < log4net > 2: <!-- Define some output appenders --> 3: < appender name ="logfile" type ="log4net.Appender.FileAppender, log4net" > 4: < file value ="log-file.txt" /> 5: < appendToFile value ="true" /> 6: < layout type ="log4net.Layout.PatternLayout" > 7: < conversionPattern value ="%d [%t] %-5p %c - %m%n" /> 8: </ layout > 9: </ appender > 10: < appender name ="ods" type ="log4net.Appender.OutputDebugStringAppender, log4net" > 11: < layout type ="log4net.Layout.PatternLayout,log4net" > 12: < conversionPattern value ="%d [%t] %-5p %c - %m%n" /> 13: </ layout > 14: </ appender > 15: < logger name ="NHibernate.SQL" > 16: < level value ="ALL" /> 17: < appender-ref ref ="logfile" /> 18: < appender-ref ref ="ods" /> 19: </ logger > 20: < root > 21: <!-- priority value can be set to ALL|INFO|WARN|ERROR --> 22: < priority value ="ALL" /> 23: < appender-ref ref ="ods" /> 24: </ root > 25: </ log4net > The log-file.txt gets all the logging I want, but I really just wanted to be able to view these statements in DebugView (gives me a bit more control in clearing out past queries, setting filters/highlight colors, etc…) I'm positive I had something like this working before but I get NOTHING in DebugView.  Anyone have any ideas as to what I'm doing wrong?  Is there a permission issue that makes this not possible? Technorati Tags: Log4Net , MonoRail , ActiveRecord , NHibernate

MonoRail Integrations

Andy Pike has recently done some really cool MonoRail integrations: Integrating reCAPTCHA with Castle MonoRail Integrating Gravatar with Castle MonoRail Take a peek at how easy it is to plug these types of things into the MonoRail framework. Technorati Tags: .NET , Castle , MonoRail
Posted by Patrick Steele's .NET Blog
Filed under: , ,

Ordering Form Collection Parameters For MonoRail using jQuery

Mike Nichols wrote a neat jQuery plugin to automatically order a list of items (like <TR>'s or <UL>'s).  This plays very nicely with MonoRail's SmartDispatcherController and DataBind attribute : "... to keep the items in a collection (like table rows or unordered lists) nicely indexed, I created a plugin that handles all the form elements for me. After ajax calls that load data into a table or ul, I can just call the plugin on the rows and all forms elements remain in their appropriate order." Check it out. Technorati Tags: MonoRail , jQuery
Posted by Patrick Steele's .NET Blog
Filed under: , ,

MonoRail Contracts

Hammet posted a couple of images he created that showed the main contracts used by MonoRail .  Pretty cool. Main Contracts Main Helpers Technorati Tags: .NET , MonoRail , Castle
Posted by Patrick Steele's .NET Blog
Filed under: , ,

Displaying an image from a database in MonoRail

Sometimes, it's just too easy! How to display an image retrieved from DB in Monorail Technorati tags: Castle , MonoRail , MVC
Posted by Patrick Steele's .NET Blog
Filed under: , , ,

Playing around with ASP.NET MVC

As I'm a big fan of Castle Project's MonoRail , I often get asked my opinion of the ASP.NET MVC stuff Microsoft is working on. And I always have the same answer -- I've seen some demos but haven't actually played around with it. So I took some time tonight and installed it. Installation You can download the ASP.NET MVC Preview 5 release here . Double-click on the MSI and you get the usual welcome screen. As always, there's a EULA to accept. After that, you're ready to install. And then you're done! Painless and easy. My First Project After installation completed, I started up Visual Studio 2008. At this point, the GhostDoc configuration screen appeared. I had to repeat my GhostDoc set up. That was weird! Don't know if that had anything to do with the ASP.NET MVC install, but I hadn't done anything else with my VS2008 installation recently. You'll now have a new Web project type called "ASP.NET MVC Web Application". After selecting this I was asked if I wanted to add a unit test project as well. Very nice! Obviously, I selected "Yes". :) My solution was now all set up and ready to go: Notice the project is pre-populated with folders for my controllers, models and views. The web.config is also fully configured. At this point, I clicked "Run" to see what would happen. By default, the web.config is not set up for debugging. I took the default and let VS.NET set up my config for debugging. And now my first ASP.NET MVC project was up and running! Comparison to MonoRail Now I started poking around the directory structure. I noticed that instead of a "layouts" folder they place their master pages ("layouts" in MonoRail) inside a "shared" folder. Sounds similar to MonoRail's shared views. I noticed that the view pages are still ASPX pages and contain a code-behind file. This seems kind of odd to me as I'm accustomed to MonoRail's view files (mostly NVelocity) -- a single file that contains everything needed to render the view; no more, no less. I could see that without discipline, the code-behind files could be bloated with business logic when it should only contain view logic. Be careful! Poking around the pre-built pages I noticed most of the "ViewData" (PropertyBag for you MonoRail people) output was wrapped in Html.Encode. It would seem to me that you'd want to, by default, always HTML encode your output (like MonoRail does). I think raw output of view data is the exception rather than the rule. Others think it should be this way too. Again, be careful! Adding a New View So it's time to start adding a little bit of my own code to this sample app. I started with adding a new view. When you do this, make sure you add a new "MVC View Page" and not the usual "Web Form": The page popped up and I noticed something right away: There's no way to pick your master page when creating a new MVC View Page. I'm sure this is just one of those things that don't exist yet. I know that this selection step is available for web forms so it's probably just a matter of time before the ASP.NET MVC stuff supports this. But, since it doesn't, you'll need to add the MasterPageFile attribute yourself as well as any ContentPlaceholder tags. I grabbed them from one of the sample pages. So now I just dumped some code real quick into the view. As I typed, I noticed the Visual Studio was complaining about what I was typing: It didn't like my "Html.Encode" nor my "ViewData" references. I copied these right from another page?! What was I missing? An import perhaps? Nope, the imports on the sample pages are the same as mine. Then it hit me -- these view pages (like web forms pages) inherit from a base class. That base class probably exposes the Html and ViewData objects. Since I just created this page (and haven't compiled), the intellisense wasn't picking up the proper settings. So even though I had the red squiggle's, I hit the build button. Everything built fine and my page errors went away. I put a line of code in one of the controllers to stick my name in the ViewData. Then I added my new page (action) to the menu: I ran the project and clicked on my link: Ok -- I admit it. Not too exciting! And it barely scratches the surface of what you can do with ASP.NET MVC. But I think I've showed it's pretty easy to install it and start using it right away -- even if you're not familiar with the MVC pattern. I'll continue to use MonoRail for my web projects as it's more mature than the ASP.NET MVC stuff. But I'll definitely be coming back to this stuff from time to time and playing around with it. I think Microsoft has made the right decision in creating a whole new architecture for implementation of the MVC pattern and not trying to jam it into the Web Forms engine. That would have been a huge mistake! Technorati tags: MonoRail...

ActiveRecord + HQL and an "IN" clause

Late last year as I was using MonoRail and ActiveRecord for a simple web application. I was helping my local church find volunteers with various skills to teach some basic computer courses to the the church staff. I wanted to keep track of the volunteers along with the skills they had. I used this as another opportunity to learn more about MonoRail and ActiveRecord. The Database The database couldn't be any simpler: I had a Trainer table, a Skill table and a join table to keep track of the 1:M relationship between a Trainer and their skills. ActiveRecord The ActiveRecord classes were equally easy to define (in fact, I created the ActiveRecord objects first and then used schema generation to generate the actual database tables). The Problem Query I used MonoRail to put together a couple of web pages for editing of the data. Then I created a "Report" page that allowed me to pick an arbritrary set of skills and get a list of all Trainers that had that particular skill. In SQL, I'd use an "IN" clause like this: select t.* from Trainer t inner join TrainerSkills ts on ts.TrainerId = t.id and ts.SkillId in (2,6) In the query above, the IN clause of (2,6) contains the primary keys of the two Skill records selected by the user. Pretty simple SQL. I needed to figure out how to get this in HQL (Hibernate Query Language). My first attempt was an almost exact port of the SQL syntax (HQL is very similar to SQL anyway): public static Trainer[] FindBySkillset(Skill[] skills) { SimpleQuery<Trainer> q = new SimpleQuery<Trainer>( "from Trainer t where t.Skills in (?)" , skills); return q.Execute(); } That didn't work. I got some cryptic error about having an "unindexed collection before []". So then I tried a variation of the above query where I used a named parameter and specifically indicated the parameter was a list: public static Trainer[] FindBySkillset(Skill[] skills) { SimpleQuery<Trainer> q = new SimpleQuery<Trainer>( "from Trainer t where t.Skills in (:skills)" ); q.SetParameterList( "skills" , skills); return q.Execute(); } That gave me another odd error. After digging around in the HQL docs as well as finding a forum post somewhere that showed a slightly different IN clause, I found out that I needed to "flip" the way I use the IN clause. In SQL, you'd say "WHERE xxx IN (values...)". In HQL, you give the list of values first and use the "elements" keyword to indicate which collection to match up those values to. The final working query: public static Trainer[] FindBySkillset(Skill[] skills) { SimpleQuery<Trainer> q = new SimpleQuery<Trainer>( "from Trainer t where ? in elements (t.Skills)" , skills); return q.Execute(); } Hopefully this helps out someone else. Technorati tags: MonoRail , ActiveRecord , HQL

Using JSON with MonoRail

As a sort of follow-up to my AJAX and MonoRail post , I've put together a small project showing how you can easily use JSON with MonoRail . I planned on posting a blog entry and the code tonight but instead, I decided to spend some time working on the AJAX and JSON section of the MonoRail Users Guide . It's my way of saying "Thanks!" to the Castle team for putting together (and supporting!) such a wonderful project. Documention always seems to lag behind features and MonoRail is no exception. While MonoRail is continually being updated and improved, the documentation is getting old and some of it hasn't even been updated since RC2 (RC3 was released in September 2007). I've submitted a few documentation patches over the past few months and tonight I submitted another one to cover the AJAX and JSON sections. It's not a complete patch, but it's a start. Hopefully, the patch will be applied within the next week or so and the result will be there for everyone to enjoy. Do you use an open source project? Have you ever dropped a note of "Thanks" to the developers or helped out with some documentation of bug fixes? Technorati tags: MonoRail , OpenSource