Chorn Sokun's Weblog

Conquer inner fear, push it to the limit!

Posts Tagged ‘Castle

Castle Routing Module

with 5 comments

In previous post I was talking about the beauty of MR Controller which I also mention about Routing feature of Castle MonoRail Framework. Today I am going to walk you through basic steps to configure environement, define and register MR Routing.

Step 1: Start with web.config by adding the following line into system.web\httpModules section

<add name="routing"
  type="Castle.MonoRail.Framework.Routing.RoutingModuleEx, Castle.MonoRail.Framework" />

Step 2: Define routing rules, base on Hammett suggestion I am going to create a static class for handling this task

// filename: RoutingRules.cs
using Castle.MonoRail.Framework.Routing;

public static class RoutingRules
{
    public static void Register(IRoutingRuleContainer rules)
    {
	  rules.Add(new PatternRoute("<controller>/[action]")
		.DefaultForArea().IsEmpty
		.DefaultForAction().Is("index"));
	// you can add as many rules as you want
    }
}

Step 3: Register rules, this have to be done once and the best place for that is in Global.asax using its’ Application_Startup event

public class Global : HttpApplication
{
    public override void Application_Start(object sender, System.EventArgs e)
    {
        base.Application_Start(sender, e);
        RoutingRules.Register(RoutingModuleEx.Engine);
    }
}

And that about it. Oh by the way if you are like me. I am a big fan of UrlHelper class and I’m addicted to this macro:

// generate url /product/list<.extension>
${Url.For({@controller: 'product', @action: 'list'})}

And if you do not want to gernerate url with extension /product/list then you have to take another step by adding the following line to monorail configuration section in the web.config

Step 4: Remove extension from generated url

<monorail defaultUrlExtension="">
    <!-- other configuration removed -->
    <url useExtensions="false"/>
    <!-- other configuration removed -->
</monorail>

Now do you have any specific routing rules wanted to discuss? It’s time to dig in ;)

Ken Egozi also had an interesting post related to this topic.

Advertisements

Written by Chorn Sokun

September 24, 2008 at 11:09 pm

jQuery ajaxform generate on the fly

with 2 comments

What scripting language would come to your mind first when you begin to talk about client-side scripting (web)? Don’t tell me it is VBScript or I’ll LOL, and so your answer would be? “JavaScript” alright +1 from me :). I believe most of the programmer who is reading this post knowing/aware of jQuery.

I can extend the talk about jQuery into a series of posts but I am not gonna do that because google would give you millions of result about jQuery and it usage.

Today what I am interested to talk about is using jQuery ajax functionality in conjunction with Castle.MonoRail to generate HTML Form on the fly and the form will also has ajax functionality. What does it mean? well let us all get into application context of adding new customer. In general we are going to have a customer page /customers which list all existing customers in a table format. Additional customer can be added by clicking on Add New Customer link wired up with a javascript function.


<a href='#' onclick='addNewCustomer()'>Add New Customer</a>

and the addNewCustomer() function looks like this:

<script language="javascript"> 

function addNewCustomer(){

   $.ajax({
      dataType: 'script',
      url: '/customers/addNewCustomer'
   });

}

</script>

From the above script the web browser going to send off a request to /customers/addNewCustomer which is going to handle by an action of CustomersController. If you care to see the action code it look like this:


[Layout("default"), Rescue("generalerror")]
public class CustomerController: SmartDispatcherController
{
    .... code removed for clarity 

    public void AddNewCustomer(){

        PropertyBag["c"] = new Customer();

    }

    .... code removed for clarity

}

and the rest of the work will be left over to the view engine to find the view template file and process it. Since I am a big fan of Brail View Engine the template file would be call AddNewCustomer.brail and the code look like this:


<form id='form1' method='post' action='/customer/create'>

   Name: ${Form.TextField("c.Name")}
   Phone: ${Form.TextField("c.Phone")}
   <input type='Submit' value='Create New' />

</form>

<script type='text/javascript'>

   $(document).ready(function(){

      $('#form1').ajaxForm( { dataType: 'script' } );

   });

</script>

Again it just simple HTML markup mixed with a few Brail’s tagging macro but take a closer look at the javascript code at bottom, what does it do? Well the idea is once the template is processed it going to generate a pure HTML form and send it back to the client side, however the javascript that send along will ensure that the new generated HTML form will perform a post back via jQuery ajax functionality. Hmm, sound cool. But didn’t I just waste a bytes of data with this approach? I tell you what, this application is going to run on a LAN so bandwidth is not a problem.

Up to this point everything works perfect, except for one final click on the Submit button to save new customer and oop! look there is a post without ajax It just work as normal as any other HTML form submission. Hmm, what I had discovered was by generating form id=’something’ or whatever as long as it is not id=’form1′. The submission of the form will route through ajax weir isn’t it? I haven’t investigate into jQuery code just yet jQuery might use form1 for something else internally, do you know what it is?

UPDATE 2008-11-25:

I believe my first assumption about form id attribute which cause ajax not to fire was wrong. What I recently found was if I am not calling $(document).ready(…); in the original page the generated dom pass in even if it contain $(document).ready(…) script block that block just do nothing.

Written by Chorn Sokun

September 21, 2008 at 9:27 pm

Posted in OSS, Programming, Tips & Tricks

Tagged with , ,

REST, Routing & the beauty of MR Controller

with one comment

What is REST?

REST stands for Representational State Trasfer an important concept in REST is the existence of resources (sources of specific information), each of which is referenced with a global identifier (e.g., a URI in HTTP).

How does it work?

REST take advantage of HTTP methods such as POST, GET, PUT and DELETE and translate the request as CREATE, READ, UPDATE, DELETE (CRUD) operation associated with database technologies.

HTTP CRUD
POST Create, Update, Delete
GET Read
PUT Create, Overwrite/Replace
DELETE Delete

REST application might define resources URI such as:

http://example.com/albums
http://example.com/albums/id
http://example.com/albums/id/slideshow

and client code would look something like this:

Resource userResource = new Resource('http://example.com/users/001');
userResource.delete();

It is simple enough, right?

RESTful Castle

REST needed URI to begin with; now if you are assigned to design a server side code for that what are you gonna do? Well, you simple need an URL Rewrite tools to save day, don’t you? So what does URL Rewrite tools do? Simply it would intercept incoming HTTP request and route to relevant destination (.php, .cgi, .aspx, .asmx scripts etc). It is pretty trivial to do it on apache web server:

  1. Make sure mod_urlrewrite is enabled
  2. define a few rules in .htaccess (hmm, regex not so funny)
And that all you need. But I am not talking about Apache I am now going to talk about .NET and the IIS to be exact I am talking about Castle.MonoRail. Castle.MonoRail is a MVC framework (MVC stands for Model-View-Controller) and I am going to dive a bit into Controller. According to the document a Controller logically grouped in an Area; and it contains Actions. For instance to produce url like this /admin/users/index.rails we simple define a controller class as:
[ControllerDetails(Area="admin")]
public class UsersController : Controller
{
   public void Index()
   {
   }
}

Notice the use of ControllerDetails attribute which usually allow you to tell MonoRail how a controller can be found. The important part of ControllerDetails above is Area = “admin” which is very flexible and that mean you can burried a controller down as deep as you want it to be.

Is that mean I can have a controller defined and it will generate URI like this?

http://example.com/albums
http://example.com/albums/id
http://example.com/albums/id/slideshow

With controller alone? you basically can’t do, because controller generated URI in the form /area/controller/action.rails?id={id} to do a nice RESTful like URI you need another tool similar to URL Rewrite lucky enough MR got a build-in tool for that it located here Castle.MonoRail.Framework.Routing … going to talk more in the future.

Limitation & Workaround

How are you going to define your controller class to fullfill the required like this?

* Public Access
http://example.com/albums
http://example.com/albums/id
http://example.com/albums/id/slideshow

* Authorization Access
http://example.com/users/albums
http://example.com/users/albums/id
http://example.com/users/albums/id/slideshow

Look at the screenshot bellow:

and you say; hell YEAH that neat right; now compile and run the test site. Navigate to /album/index.rails work unfortunately navigate to /users/albums/index.rails will cause MR to throw an exception say it can’t find Area & Controller specified.

What the hell ??? the truth is MR register a controller using class name as a key I believe it run from the top namespace first which mean Basic.Web.Controllers.AlbumController got register first so when it walk into Basic.Web.Controllers.Users.AlbumController it just skip that controller.

To work around this problem against thank to ControllerDetailsAttribute which allow us to name a controller free from Controller class. How are you going to do that? well rename /users/AlbumController.cs to /users/WhatTheF_CKAlbumController.cs and boom it done.


[ControllerDetails("album", Area="users")]

public class WhatTheF_CKAlbumController{

    ... same code old code

}

Get lost? probably :) but don’t worry I am going to give a slow version in my C# lecturing session and if you are interested to walkin and listen up just subscribe to my google calendar.

Until then have a good weekend.

Written by Chorn Sokun

September 20, 2008 at 6:01 am

Posted in MonoRail, OSS

Tagged with , ,

ASP.NET Globalization & Localization Take #2

leave a comment »

In my previous post “.Net 2.0 App_GlobalResources within VS.NET 2008” I was successfully manipulate string stored in satellite assembly that was the isolation test to make sure that thing work. 

ASP.NET Web Application Basic Structure

ASP.NET Web Application Basic Structure

The next move is to integrate the technique with my MonoRail solution. In theory the trick should work like magic;

Castle Basic Structure

Castle Basic Structure

BUT nope I got nothing in return I verify the satellite assembly through Reflection nothing different. So what the heck is going on ???

Now take a look at how I solved the mismatch:

ASP.NET Web Application

ResourceManager rm = new ResourceManager(
   "Web.Applications2.Strings", Assembly.GetExecutingAssembly());

Castle.MonoRail

ResourceManager rm = new ResourceManager(
   "Basic.Web.Resources.Strings", Assembly.GetExecutingAssembly());

Can you spot the different?

Written by Chorn Sokun

September 10, 2008 at 2:03 pm

Rhino-Tools

with 3 comments

Ayende’s Rhino-Tools become the most wanted library for my next project, consuming open source library with lack of walkthrough sample/enough test suite is always a painful experience “at the beginning”. It makes me stress for sometime as I can’t find any peer near by to share the experience with and yeah I tell you if you’ve got weak heart and usually depend on external person to walk you through the percentage of success is very low.

“No Pain, No Gain”, although the OSS’s troop are miles aways I’ll keep standing still until my last breath and hopefully, hopefully the support troop would come along.

So on the next day(s) I found the following post appear on the net which help me stand again.

Now I know how to spend my next weekend, thanks to all the good works and the sharing.

Written by Chorn Sokun

June 3, 2008 at 10:47 am