Home

Castle Stronghold

Using the SmartDispatcherController

Although our controller extends from SmartDispatcherController we haven't used any of its capabilities. The SmartDispatcherController, as the name implies, implements a smart way to invoke actions. Query string entries, form entries and even cookies can be bound actions parameters. For example, suppose you have the following form on a view:


<form action="/home/saveinformation.castle" method="post" >

    <input type="text" name="name" value="John doe" />
    
    <input type="text" name="age" value="30" />
    
    <input type="text" name="dob" value="07-16-1979" />

    
    <input type="submit" value="Send" />

</form>

You can create the action SaveInformation in a way that it will expect the parameters:


public class HomeController : SmartDispatcherController
{
    public void Index()
    {
    }
    
    public void SaveInformation(String name, int age, DateTime dob)
    {
        // work work work
        
        // Send the user back to the index 
        RedirectToAction("index");
    }
}

The code above saves you the hassle of using the Params or Form name-value collections. It is basically equivalent to the following code:


public class HomeController : SmartDispatcherController
{
    public void Index()
    {
    }
    
    public void SaveInformation()
    {
        String name = Params["name"];
        int age = Convert.ToInt32(Params["age"]);
        DateTime dob = Convert.ToDateTime(Params["dob"]);
    
        // work work work
        
        // Send the user back to the index 
        RedirectToAction("index");
    }
}

But much cleaner and simpler. It is able to handle a diversity of types, for more on this check the SmartDispatcher reference documentation.

Using the DataBind attribute

You can also use the SmartDispatcherController to populate entire objects. To exemplify that lets create a contact form so the user can contact some department from our ficticious company.

  1. Create a new controller named ContactController and include two actions: ContactForm and SendContactMessage.

    
    namespace GettingStartedSample.Controllers
    {
        using System;
        using Castle.MonoRail.Framework;
    
        [Layout("default"), Rescue("generalerror")]
        public class ContactController : SmartDispatcherController
        {
            public void ContactForm()
            {
            }
            
            public void SendContactMessage()
            {
            }
        }
    }
  2. Create a class Contact that represents the contact information.

    
    public class Contact
    {
        private string from;
        private string area;
        private string subject;
        private string message;
    
        public string From
        {
            get { return from; }
            set { from = value; }
        }
    
        public string Area
        {
            get { return area; }
            set { area = value; }
        }
    
        public string Subject
        {
            get { return subject; }
            set { subject = value; }
        }
    
        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }
  3. Now create the view for the ContactForm action. The view name should be contactform.vm and should be put on Views\Contact folder.

    
    <h2>Contact us!</h2>
    
    <p>
    We are interested in hearing from you.
    </p>
    
    <form action="SendContactMessage.rails" method="post">
    
    <p>
    From: $FormHelper.TextField("contact.from")
    </p>
    
    <p>
    Area: $FormHelper.TextField("contact.area") (Sales, Support)
    </p>
    
    <p>
    Subject: $FormHelper.TextField("contact.subject", "%{size='30'}")
    </p>
    
    <p>
    Message: <br/> 
    $FormHelper.TextArea("contact.message", "%{cols='35', rows='6'}")
    </p>
    
    <hr />
    
    <p>
    <input type="submit" value="Send the message" />
    </p>
    
    </form>

    Note that we used the FormHelper which handles generation of form elements. You can (and should) learn more about helpers and especially the FormHelper on the documentation.

    You should also note that the each generated field on the html will be prefixed with contact, for example contact.name. This is important as to use MonoRail's data bind you must prefix the form elements to avoid name clashes.

  4. Finally change the action to bind the form data to the Contact class:

    
    public void SendContactMessage([DataBind("contact")] Contact contact)
    {
        // Pretend to save the contact ...
        
        // ..work work work..
        
        // Now lets add the contact to the property bag
        // so we can render a nice message back to the user
        
        PropertyBag["contact"] = contact;
        
        RenderView("confirmation");
    }

    We used the DataBindAttribute on the action parameter. Its first parameter is the prefix used on the form. In our case it is contact. When this action is invoked, MonoRail will try to match the form data with the properties on the Contact class and create an new instance populating the properties.

  5. It would be nice to create the confirmation view too:

    
    <p>
    
    Thanks $!contact.from, we have received your message and will
    get back to your shortly.
    
    </p>
        

Now test your work by running the application and accessing /contact/contactform.rails. Fill the form elements and submit it.

Proceed with Bringing ActiveRecord to the party.

Google
Search WWW Search castleproject.org