Chorn Sokun's Weblog

Conquer inner fear, push it to the limit!

Archive for the ‘MonoRail’ Category

Deploy MonoRail on IIS7

with 3 comments

Note to myself

1. On Default Web Site, click Add Application

2. Change Application Pools = Classic .NET AppPool , go to Application Pools and click on Classic .NET AppPool then take Advanced Settings

Calssic .NET Application Pools, Advanced Settings

3. Add the following setting to web.config

	<system.webServer>
		<handlers>
		  <clear />
		  <add name="PageHandlerFactory-ISAPI-2.0-64" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
		  <add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
		  <add name="MonoRail64" path="*.castle" verb="*" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="4194304" />
		  <add name="MonoRail" path="*.castle" verb="*" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="4194304" />
		  <!--
		  <add name="UrlRewriting64" path="*" verb="*" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="None" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="4194304" />
		  <add name="UrlRewriting" path="*" verb="*" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="None" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="4194304" />
		  -->
		  <add name="StaticFile" path="*" verb="*" type="" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" scriptProcessor="" resourceType="Either" requireAccess="Read" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" />
		</handlers>
	</system.webServer>

We good to go, hope I don’t waste my time again on this thing.

Written by Chorn Sokun

November 4, 2010 at 4:10 pm

MR, Ambiguous controller names

leave a comment »

Reading through Phil Haack’s post implication in supporting area in ASP.NET MVC 2 remind me the time I faced the same problem using MonoRail, I believe I had post my solution in the passed but I can’t dig inside my blog entry to get it back.

So here it goes again the trick I used in to fix the problem let assume I had Admin Area & User Area and each has a HomeController I then would create controller file like this:

  • Admin [ Folder ]
    • AdminHomeController.cs
  • User [ Folder ]
    • UserHomeController.cs

Then I need to use ControllerDetails attribute to give these two controller a prefer url

// access with /admin/home/index.castle
[ControllerDetails("home", Area="admin")]
public class AdminHomeController: SmartDispatcherController { ... }

// access with /user/home/index.castle
[ControllerDetails("home", Area="user")]
public class UserHomeController: SmartDispatcherController { ... }

That work for me !

Written by Chorn Sokun

January 13, 2010 at 9:38 pm

Posted in MonoRail, Tips & Tricks

Use jQuery to catch and display MR AJAX errors

with one comment

This post influenced Dave Ward’s post to replicate the behavior that he discussed within MonoRail application.  To mimic this behavior I created a method call RenderJsonError(Exception ex) inside my base controller (I want to reuse this method)

public abstract class AbstractBaseController: ARSmartDispatcherController{
   private void RenderJsonError(Exception ex){
      CancelLayout();
      Response.StatusCode = 500;
      Response.ContentType = "application/json; charset=utf-8";

      // I love this Framework :)
      var json = Context.Services.JSONSerializer.Serialize(
         new ErrorObject(){
            Message = e.Message,
            StackTrace = e.StackTrace
         });

      RenderText(json);
   }
}

From the code above look like I need to create a dummy DTO class ErrorObject and hand it over to JSONSerializer service instead of doing string escape/string concat myself :) MR use Newtonsoft.Json.dll behind the scene.

public abstract class AbstractBaseController: ARSmartDispatcherController{
  ....
  internal class ErrorObject{
     public string Message { get; set; }
     public string StackTrace { get; set; }
  }
}

Now let through some booms back to client

public class HomeController: AbstractBaseController{
   public void Index(){
      try{
          throw new Exception("Boom ! boom !");
      }catch(Exception ex){
          RenderJsonError(ex);
      }
   }
}

That work ! however if you don’t want to deal with try{..} catch {..} then combine this technique with RescueAttribute describe in my previous post.

Written by Chorn Sokun

October 2, 2009 at 12:58 am

Posted in MonoRail

Tagged with ,

MonoRail, IRescueController Handle Unexpected Exception

with one comment

By default you can intercept unexpected exceptional error occur in MonoRail you can opt to render a specific view from Views/Rescues folder or let MR pick standard one such as 404 page not found …

How how about you want to log the exception then you need to build a custom controller class that implement IRescueController interface just like this:

public class RuntimeExceptionController : SmartDispatcherController, IRescueController
{
  public void Rescue(Exception exception, IController controller, IControllerContext controllerContext)
  {
    // ... log via log4net ...
    // ... render & send error back home :) whatever you find helpful
  }
}

// usage: simple
[Rescue(typeof(RuntimeExceptionController))]
public class HomeController: SmartDispatcherController{
  public void Index(){
     throw new Exception("Boom !");
  }
}

Written by Chorn Sokun

October 1, 2009 at 10:38 am

(N)How simple could that be?

with 2 comments

projection-skill-in-action

Wonder how this report get produced from model above it? If you guess was

  • NHibernate
  • MR (did you say <table>?)

You right and I must say I finally master the NH Projection skill or in another word (stealling from JXII) level up!.

What I did by taking AreaCode as primitive data connect it through and transform set of progress records into columns pretty cool trick, no NH hack is required it all natural.

Happy Projections day

Written by Chorn Sokun

May 29, 2009 at 12:19 pm

MonoRail & jQuery

leave a comment »

Last year I blog about using jQuery.ajaxForm() to send http post request to MonoRail action and finally it depend on JSGenerator to produce javascript and send it back to client.

But overtime I find it pretty scary using that approach:

  • It give too much control to the server – the server can generate a bunch of javascript and send off to the client sort of invade client responsibility.
  • In some scenario I even specify from the server which div element I want to render my data table in
  page.ReplaceHtml('#divId', "content_to_be_replace_from_server")
  • using approach in previous post I was not be able to ensure 100% that if I send piece of jquery script that it combine into the main DOM properly for instance I did have a form & a jQuery to confirm the form into ajaxForm but that behavior is not always reliable.

So what the deal now? well, I happen to change the strategy a while ago just haven’t got time to blog about it the solution is pretty simple “Don’t make JSGenerator your new hammer.”, Let see my simplify approach:

<div id='dlist'>
  <!-- I am going to render list of data in this div --></div>
<input type="button" value="Show data" onclick="showData();" />
<input type="button" value="Add more" onclick="addData();" />
<div id='dform' style='display: none;'>
  <!-- I am going to load form into this div --></div>

That pretty normal HTML markup right? 2 div one for display list of data second one for display form for adding more data and I also have 2 buttons to invoke client script (jQuery).

<script>
function showData(){
   $('#dlist').load( '/task/list.rails', {'status': 'incomplete'} );
}

function addData(){
   $('#dform').load( '/task/add.rails', {}, function(){
      $('#dform').show();
    });
}
</script>

Now that instead of using $.ajax I use $(‘#elementId’).load() instead because load() will inject html render by MonoRail action in the DOM and it just as native element.

Note : line 07 dform had style apply so that without having form inside it don’t occupy space in the page however one content loaded we need to set visibility for it.

For your reference the final piece of the puzzle is purely view code like this (View\task\add.brail)

<form method='post' id='taskForm' action='/task/create.rail'>
  Name: <input type='text' name='t.Name' />
  <input type='submit' value='Create' />
</form>

<!-- not inject some jQuery script along make the form submit via ajax -->
<script>
   $(function(){
       $('#taskForm').ajaxForm ({
          success: function(response){
            $('#dlist').html(response);
          },
          error: function (xhr, status, error) {} // handle error if you wish
        });
   });
</script>

Notice on line #09 : need the form to submit using ajax and line #11 the client take control where it want to place the result (list of task).

It seem like we have to write a bit more code (jQuery) but after all that the fun part of being a programmer write code that :) Hope this would help.

Written by Chorn Sokun

March 26, 2009 at 9:13 pm

Posted in Castle, MonoRail, Tips & Tricks

Tagged with ,

MonoRail vs ASP.NET MVC Take #1 HTTP verbs

with 2 comments

Along came ASP.NET MVC although I am not the fan of ASP.NET MVC but it doens’t heard reading ASP.NET free chapter (nerddinner) and I did learn a few tricks, I will try my best to map concept between the two framework now let see

Why differentiate via HTTP verbs? read the book and find out, but here the deal

  • ASP.NET MVC [AcceptVerbs(HttpVerbs.Post)]
  • and [AccessibleThrough(Verb.Post)] in MonoRail
// GET: /Payroll/Delete/2
public void Delete([ARFetch("id"}] Payroll payroll){
   if (payroll == null)
   {
      RenderView("InvalidRequest");
   }
   else
   {
       PropertyBag["payroll"] = payroll;
       RenderView("DeleteConfirm");
   }
}

// POST: /Payroll/Delete/2
[AccessibleThrough(Verb.Post)]
public void Delete([ARFetch("id"}] Payroll payroll, bool confirm){
   if (payroll == null)
   {
      RenderView("InvalidRequest");
   }
   else
   {
      if(confirm){
     ..... // drop the record off the database
     ..... // do whatever you want.
      }
      else
      {
          RedirectToAction("Delete", "id"  + payroll.Id);
      }
   }
}

MonoRail Rock!

Written by Chorn Sokun

March 26, 2009 at 10:17 am

Posted in Castle, MonoRail, Tips & Tricks

Tagged with