Wednesday, November 12, 2008

How to display an image retrieved from DB in Monorail

Assume that I am developing a Castle Monorail Web application.

If I want to display an image retrieved from the database on a web page I can use a view template which looks similar to this one

<div>
  <table class="form">
    <tbody>
      <tr>
        <td>Title:</td>
        <td>${Form.TextField("model.Photo.Title")}</td>
      </tr>
      <tr>
        <td>Comment:</td>
        <td>${Form.TextArea("model.Photo.Comment")}</td>
      </tr>
      <tr>
        <td><button id="selectImage">Select</button></td>
        <td><img src="${UrlHelper.For({@action:@getPhoto})}?photoId=${model.Photo.Id}"/></td>
      </tr>
    </tbody>
  </table>
</div>

Note that I am using Brail as my view engine. I have an <img> element in the template. The src attribute of the <img> element points to the getPhoto method of the controller. The code in the controller which provides the photo is

public void GetPhoto(Guid employeePhotoId)
{
    var model = service.GetEmployeePhoto(employeePhotoId);
    Response.ContentType = "image/gif";
    Response.BinaryWrite(model.Photo.Image);
    CancelView();
}

Here the call to the service returns a model having a public field Photo. The class representing the photo has (among others) properties Title and Image, where Image is an array of bytes containing the photo itself (e.g. the content of a gif or jpg image).

Friday, September 19, 2008

jQuery and unit testing

The following blog post of Chad Myers gives a good introduction to unit testing of jQuery client side Java Script with the aid of QUnit.

And this post of Joshua Flanagan is a follow up which explains how one could integrate the QUnit tests into a CI build.

Note: NUnit has to run on a single threaded apartment thread [STA]. To do this add an app.config to your test assembly with the following content

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="NUnit">
      <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
    </sectionGroup>
  </configSections>
  <NUnit>
    <TestRunner>
      <add key="ApartmentState" value="STA" />
    </TestRunner>
  </NUnit>
</configuration>

Monday, September 1, 2008

How-To add a custom validation method to the jQuery validator plug-in

For my current project I needed a custom validator method for the jQuery validator plug-in. I wanted to validate that a user has chosen a value from a combo box where the value is of type Guid.

First I implemented a JavaScript function which tests whether a given value represent a valid Guid but not an empty Guid (An empty Guid has the following form: 00000000-0000-0000-0000-000000000000). To achieve this result I use regular expressions

var isValidGuid = function(value) {
  var validGuid = /^(\{|\()?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(\}|\))?$/;
  var emptyGuid = /^(\{|\()?0{8}-(0{4}-){3}0{12}(\}|\))?$/;
  return validGuid.test(value) && !emptyGuid.test(value);
}

The above function returns true for a valid Guid and false for every thing else.

Now I have to add this validation method to the validator plug-in as follows

$.validator.addMethod("isValidGuid", function(value, element) {
  return isValidGuid(value);
}, 'Please select a valid and non empty Guid value.');

Finally I can use this custom validation method on any form element by assigning it the class isValidGuid, e.g.

<select id="title" class="isValidGuid" title="Please select a title!">
  <option value="00000000-0000-0000-0000-000000000000" selected="selected">(select)</option>
  <option value="33a1eb15-cdbc-4c85-be01-dcb4f393c0a5">Engineer</option>
  <option value="43b5d0f7-4915-41f1-b3b9-d6335299cc22">Physicist</option>
  <option value="d80322f2-bb76-447c-a6ac-77f145bac70d">Technician</option>
</select>          

when applied we have the following outcome

image

Friday, August 22, 2008

JavaScript: access properties of a complex JSON object

Lately I needed to dynamically access the value of a nested property in a complex JSON object in a JQuery plug-in I wrote. Since to my knowledge this is not possible directly I wrote a little function in Java Script.

var findValue = function(item, name) {
    var token = /\w+/g;
    var results = name.match(token);
    var temp = item;
    for (var i = 0; i < results.length; i++)
        temp = temp[results[i]];
    return temp;
}  

First I use a regular expression to find all property names which are separated (witch are separated by a dot in my case). Then I loop over the matches and move forward in the object tree.

If I now have an object as follows

var item = {
  Id: 1,
  Name: { FirstName: "Gabriel", LastName: "Schenker" },
  ...
}

I can access the value of the LastName property with this function call

findValue(item, 'Name.FirstName')

Enjoy!

Wednesday, July 2, 2008

HowTo use Castle Monorail and jQuery to exchange JSON data

Define a Controller as follows

[Layout("default")]
public class JsonController : SmartDispatcherController
{
    public void Index()
    { }
 
    /// <summary>"Manual" or "traditional" way to return 
    /// JSON formatted data</summary>
    public void GetStates(string countryCode)
    {
        State[] states = FetchAllByCountry(countryCode);
 
        string js = Context.Services
                       .JSONSerializer
                       .Serialize(states);
 
        Response.ContentType = "application/json";
        RenderText(js);
    }
 
    /// <summary>
    /// Return JSON formatted data by using an attribute
    /// One can even filter the list of fields that should
    /// be serialized
    /// </summary>
    /// <returns>the JSON formatted list of states</returns>
    [return: JSONReturnBinder(Properties = "Id,Name")]
    public State[] GetStates_Ex(string countryCode)
    {
        return FetchAllByCountry(countryCode);
    }
 
    private static State[] FetchAllByCountry(string countryCode)
    {...}
}

The State entity is defined as

public class State
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

The JSON output generated by the method GetStates is similar to this

[{"Id":1,"Name":"ZH","Description":"Zürich"},
 {"Id":2,"Name":"TG","Description":"Thurgau"},
 {"Id":3,"Name":"SG","Description":"St. Gallen"}]

and the output from GetStates_Ex is similar to this

[{"Id":1,"Name":"ZH"},
 {"Id":2,"Name":"TG"},
 {"Id":3,"Name":"SG"}]

Note that in the latter case the field Description is not included as expected!

In the index.brail template (I'm using the brail view engine) use the following java script block

<script>
    jQuery(document).ready(function(){
        jQuery("#traditional").click(function(){
            jQuery.getJSON("${UrlHelper.For({@action:@GetStates})}",
                function(data){
                    jQuery.each(data, function(i,item){
                        jQuery("<div/>").text(item.Name)
                            .appendTo("#states");
                    });
                });
        });
        
        jQuery("#withAttr").click(function(){
            jQuery.getJSON("${UrlHelper.For({@action:@GetStates_Ex})}",
                function(data){
                    jQuery.each(data, function(i,item){
                        jQuery("<div/>").text(item.Name)
                            .appendTo("#states");
                    });
                });
        });
    });
</script>

and the following HTML

<button id="traditional" >Traditional</button>&nbsp;
<button id="withAttr" >with Attribute</button>&nbsp;
<br />
<div id="states"></div>

Clicking on either the first or the second button will make an Ajax call to the controller and return a JSON serialized list of states. When returning from the call the names of the states are displayed in the div with id="states".