Showing posts with label monorail. Show all posts
Showing posts with label monorail. Show all posts

Tuesday, May 13, 2008

Registering MonoRail Extensions Programatically

Hammett inspired me to switch from XML configuration to programmatic configuration of MonoRail with this blog post. But he didn't discuss how to configure MonoRail extensions. I searched around through the source and came up with this solution:

        public void Configure(IMonoRailConfiguration configuration)

        {

            configuration.ViewEngineConfig.ViewPathRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views");

            configuration.ViewEngineConfig.ViewEngines.Add(new ViewEngineInfo(typeof(NVelocityViewEngine), false));

 

            configuration.ConfigurationSection = new MutableConfiguration("monorail");

            configuration.ConfigurationSection.Children.Add(

                new MutableConfiguration("exception")

                    .CreateChild("exceptionHandler")

                    .Attribute("type", typeof(EmailHandler).AssemblyQualifiedName)

                    .Attribute("mailTo", "to@email.com")

                    .Attribute("mailFrom", "from@email.com"));

 

            configuration.ExtensionEntries.Add(

                new ExtensionEntry(typeof(ExceptionChainingExtension), new MutableConfiguration("")));

        }



This code sets up the EmailHandler that comes with MonoRail.

Thursday, October 18, 2007

MonoRail Routing Upgrade Coming

I just did an update from the Castle repository, and look what I found:


Looks like we may be seeing improved routing capabilities in MonoRail soon. Isn't open source grand?

Wednesday, October 17, 2007

Castle MonoRail vs Microsoft MVC

Everyone seems to be chiming in on the newly announced MVC framework from Microsoft. A lot of the posts seem to be very positive.

The most talked about features seem to be:

  • Routing

  • Mockable IHttpRequest/IHttpResponse

  • Type-checked views


The routing feature seems pretty nice, but how far is MonoRail from having this feature? I think that MonoRail is missing this feature mainly because it wasn't developed in the era of IIS6.

IIS7 as I understand it gives the web application access to the web request earlier than IIS6, which gives it more control over the routing capabilities. Currently, IIS6 is not really well suited to be able to handle routing requests when there's no file extension on the URL. I imagine that this feature could be added fairly quickly once there's more motivation and more adoption of IIS7.

The mockability of IHttpRequest and IHttpResponse is a pretty nice feature as well, but couldn't MonoRail do this? Scott Guthrie said that they didn't change ASP.NET at all to get this feature.

Couldn't MonoRail wrap the standard HttpResonse and HttpRequest objects with adapters that implement a similar interface? The major hurdle with this seems to be that this wasn't done in the first place, and there's a lot of code out there that would have to change to use the new interfaces.

I have to admit that type-checked views sound enticing. It would be pretty cool to have refactoring operations automatically change things in the views.

But I've lived in a compiled view world and I really don't want to go back. If I have to recompile my project because I changed something in the view I would be pretty annoyed. It's already a huge annoyance to have to wait for the AppDomain to reload when I change something in a controller. I really don't want to wait for it to reload when I change a view as well.

I remember back in my Java/Struts days, I welcomed a switch in our project to Velocity over JSP files. There was a huge increase in productivity and I really didn't miss the type checking at all.

I love being able to submit a patch or jump on the Castle mailinglist to discuss a quick change that would help my own project and have the change implemented within hours or days. Wouldn't you lose that ability if you switched to Microsoft's MVC?

I guess that's a standard issue when deciding between open source and commercial frameworks. I'm really not ready to give that up, and I think that's one of the main reasons I'll be sticking with MonoRail as long as the project remains as active as it is.

Overall, I am pleased with the announcement. It seems that Microsoft is watching what is going on the community and trying to deliver a better platform for developing web applications.

My main point is that MonoRail is already a great platform that's in use by many, it's actively developed, and I'd be surprised if this new platform from Microsoft doesn't push it to greater heights. As always though, I'll be keeping an open mind as things unfold.

Tuesday, July 10, 2007

MonoRail Exception Chaining

MonoRail comes with a nice exception handling mechanism. It's pretty well documented so I won't explain how it works.

MonoRail also provides an handler that sends an email with exception and request details. I got tired of getting this email in my development environment, so here's what I came up with:

    public class ExceptionFilterHandler : AbstractExceptionHandler

    {

        public override void Process(IRailsEngineContext context)

        {

            if (context.Request.IsLocal)

                return;

 

            InvokeNext(context);

        }

    }



Pretty simple and it does the trick. This also gives you the ability login to the server in production if you have access and see the exception detail in the browser instead of getting an email. It checks to see the web request was made from the local machine.

Saturday, April 28, 2007

Rendering Binary Data with MonoRail

Sometimes you want to make your MonoRail controller render binary data for a download. MonoRail by default is setup to render HTML via the view engine, but you can change that behavior. I usually put a method like this in my base controller:

        protected void SetupDownload(string filename, string contentType)

        {

            CancelLayout();

            CancelView();

            Response.Clear();

            Response.ContentType = contentType;

            Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        }



By calling this method inside one of your controllers, you will change the default behavior of the controller to not perform the layout (CancelLayout()) and to not try to render a view via the view engine (CancelView()). The contentType should be something like "application/zip". It's the MIME type that is reported to the browser. This method also tells the browser that the data is not inline, and that the user should be prompted to download the file with a default filename provided by the filename argument.

So you have changed the default behavior of MonoRail to render something other than a plain vanilla view. All that's left is to write the binary data into the response's output stream. If you already have a stream, then you would do something like this:

        private void CopyStream(Stream from, Stream to)

        {

            byte[] buffer = new byte[_bufferSize];

            int bytes = 0;

            while ((bytes = from.Read(buffer, 0, buffer.Length)) > 0)

                to.Write(buffer, 0, bytes);

        }



            CopyStream(System.IO.File.OpenRead(path), Response.OutputStream);



Or, if you have a byte array (buffer in this example) or something similar, you can do something like this.

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



Notice that if you want to have the brower render something inline (e.g. an image), than you can just remove line that adds the Content-Disposition header that is in my example SetupDownload function.