views:

437

answers:

2

Hello...

My project is using Castle Monorail as a MVC framework. The problem is that Monorail requires that all controllers have a view template. I am trying to get a string back from a method on a controller via an AJAX call. The AJAX GET always returns a 500 error from the server because Monorail cannot find a view template. I have seen other examples of workarounds in which you just set the return type of the controller method to void (this signals monorail to not bother finding a view controller) and then doing something like:

Context.Response.OutputStream.Write(buffer, 0, buffer.Length);

To just write the context to the screen.

So I have the follow method and am trying to get the return string via a Jquery AJAX GET. Can someone help?

 public void Note(string id)
    {
        if (!string.IsNullOrEmpty(id))
        {
            if (notesProvider.HasNote(id))
            {
                return "{status:'200', text: '" + notesProvider.GetNote(id).Body + "'}";

            }
            else return "{status:'404', text: 'Could not find the Note by provided id [" + id + "]'}";
        }
        else return "{status:'500', text: 'Illegal request : a note id must be provided'}";
    }
}

How should I make this return void and read the return values via the HTTPCOntext?

+1  A: 

All derived Monorail Controllers have access to a method called, "CancelView()". Execute this method within the method that you wish to return without using a view template.

Nick
A: 

You can use the JsonReturnBinder for that:

[return:JSonReturnBinder]
public object Note(string id)
{
    if (!string.IsNullOrEmpty(id))
    {
        if (notesProvider.HasNote(id))
        {
            return new {status=200, text= notesProvider.GetNote(id).Body };
        }
        else return new {status=404, text="Could not find the Note by provided id [" + id + "]" };
    }
    else return new {status =500, text="Illegal request : a note id must be provided" };
}

Refinement suggestion:

Why return the status code as part of the response body? there is the HttpStatusCode field in any response. Setting it to the desired code will make client code easier to use (you can inspect the status code in the XMLHttpRequest directly, and most JS libraries has dedicated handlers for success and errors), plus your method will return the desired string, so Unit Testing would be much easier. Example:

[return:JSonReturnBinder]
public string Note(string id)
{
    if (!string.IsNullOrEmpty(id))
    {
        if (notesProvider.HasNote(id))
        {
            return notesProvider.GetNote(id).Body;
        }
        else 
        {
            Response.StatusCode = 404;
            return "Could not find the Note by provided id [" + id + "]";
        }
    }
    else 
    {
        Response.StatusCode = 500;
        return "Illegal request : a note id must be provided";
    }
}

Another suggestion - shuffle the if/else blocks to reduce nesting levels:

[return:JSonReturnBinder]
public string Note(string id)
{
    if (string.IsNullOrEmpty(id))
    {
        Response.StatusCode = 500;
        return "Illegal request : a note id must be provided";
    }

    if (notesProvider.HasNote(id) == false)
    {
        Response.StatusCode = 404;
        return "Could not find the Note by provided id [" + id + "]";
    }

    return notesProvider.GetNote(id).Body;
}

This way the code begins with safeguards (pre-conditions), and the last return statement in the method represents the normal execution completion. IMO it makes things easier to read.

Ken Egozi