Archive for the ‘MonoRail’ Category

MR3 – *very* high level overview

February 26th, 2012

Picture = thousands of words, right?

MR 3 update / Castle Blade

July 18th, 2011

Fun times! Since I’ve left MS I’ve been working on a real web site/backend/frontend – you know, doing actual work instead of long meaningless meetings, doc writing and one-on-ones with managers setting you up for failure (I wonder if I should make one of my ‘reviews’ public, so you’ll see the amount of BS I had to put up with).

WebSockets

Anyway, the first work was to create a websockets server. That was fun especially since F# offers its async workflow support and MailboxProcessor. It’s fun to think about it. While at MS, one of my friends there wouldn’t stop bitching about how F# is incredibly superior to C#. Gosh, he was right..

The company I’m doing the work for and I are discussing whether we will make the websocket server available commercially. It’s a PITA to implement the protocols, to test them and keep up, since the spec is in progress. So, sorry, won’t be doing all this work for free.

Ideas playground

On the MonoRail end, we’ve been using it extensively and coding up functionality as needed – by we I mean Henry and I. It’s been quite a journey to reassess all the design decisions in MR1/2, and also evaluate what’s out there. I’m sure we learn more from our mistakes than anything else. Mauricio is pushing some interesting ideas on web frameworks that are making me reevaluate our proposed API over and over again. Now that I’m quite familiar with FParsec, the idea of using combinators to compose forms (formlets) is enticing. It’s just strike me as something hard to expose in C#, we would need a different API and I’m sure it would be awfully verbose.

Castle.Blade = ++Razor

I love Razor’s simplicity and tooling support. Achieving simplicity is a major accomplishment, and the guys at the ASP.NET team did it. I remember when Scott Hunter gave us a preview of what at the time was code named Plan9. Awesome work!

I’ve then decided to make Razor the main view engine for MR3. However, when I started to experiment with a better API for our helpers library I bumped into some not-so-nice limitations from Razor. For example, I wanted to be able to express something like:

 Rails |  copy code |? 
1
2
@Form.For(..., {
3
	// this is a block
4
        @builder.EditorFor(m => m.Name)
5
})
6

Well, Razor does support translating a mix of content and code block into a delegate – which is neat. The limitation is that they cannot be nested, and the parameter name is restricted to “item”

 Rails |  copy code |? 
1
2
@Form.For(..., @{
3
        @item.EditorFor(m => m.Name)
4
})
5

The issue is that “item” is not very expression. I’ve spent many hours digging into Razor’s code trying for find a way to work-around this limitation (by using its extension points, not changing their code). At some point it was clear that coding up my own parser and translator would be easier. Castle Blade then came to fruition.

Blade intends to be 100% backward compatible with Razor, and introduces a few (one?) different transition marks to overcome Razor’s limitations. For the example above, we would use:

 Rails |  copy code |? 
1
2
@Form.For(..., @=> builder {
3
        @builder.EditorFor(m => m.Name)
4
})
5

The @=> transition signals that a delegate will be created for the block, and the parameter name is the one that follows. In theory more than a single parameter is supported.

We also support nested blocks, which allows for the something like the following:

 Rails |  copy code |? 
01
02
@Form.For(..., @=> builder {
03
        builder.FormTemplate(@=> t {
04
                <div>
05
                    @t.Label(): @t.Field()
06
                </div>                                                      
07
            });
08
 
09
        <fieldset id="contactForm">    
10
 
11
        @builder.TemplateFor( m => m.Name )
12
        @builder.TemplateFor( m => m.Email )
13
 
14
        </fieldset>
15
})
16

Feel free to give it a try.

MonoRail+++

MonoRail’s 3 goal is based on our my experience and perception of the “state of the union” and trends. If I could put them in three simple statements:

I’m mentally tired of crafting web sites despite huge functionality overlaps (combine/compose). I’m tired of REST being an afterthought to existing websites (rest support from the beginning). I’m tired of frameworks created by people without *actual* website building experience (frictionless).

The goals/roadmap/value-proposition were discussed in the past in our development list.

  • Since our underlying runtime (CLR) is keen on static typing then fully embrace it
  • Move forward: embrace HTML 5
  • Simplify special render for different form factors
  • Strive for simplicity, but no simpler

I’ll dive into what’s been done in practice to address each of the above bullets in upcoming blog posts.

MonoRail+++

September 13th, 2010

It’s been more than six years since the first prototype of MonoRail appeared on Castle’s SVN repository. By then our website was hosted in a linux machine, the web server was Webrick, running a beta version of Rails, and had to be restarted once per day (at least) due to memory leaks. WebForms was the winner in the .net space, Struts the winner in the java space (unbelievable!), cocoon committers were toying with the idea of implementing continuations, probably inspired by Seaside.

Back then I was fresh back from London (now you know where Windsor’s name came from), jobless, and entertaining with the idea of setting up a small software shop with Carlos and Rodrigo. One of the first challenges was to pick the technology to invest and potentially create a small product. Rodrigo was obviously biased towards .net with boo. I was playing with Ruby/Nitro. Carlos was inclined towards webforms with c#. We decided to pick one each, build somewhat similar and compare/contrast. AFAIK Rodrigo picked up some Java tech, Carlos chose boo, and I went with Rails.

I fell in love with Rails and became a strong advocate. However, as “our product” grew in complexity, Rails – by then – didn’t catch up. Big refactorings were hard due to the dynamic nature of Ruby, lack of unicode was a red flag for i18n, leaks and bad performance (couldn’t get fastcgi to work on apache!). Also, the ecosystem, the libraries for dynamic image generation were badly maintained, if ever…

That’s when I decided to combine the philosophy of Rails with the solid foundation of .net. By then it was called Castle on Rails.

Things have changed since then. MonoRail seems to have greatly inspired Microsoft’s take on Model-View-Controller for the web. Mongrel, Merb and REST ascendance, a ton of great ideas continue to appear in the Ruby community. Same in a slower pace for other communities.

 

Web apps then and now

While there was dynamicity in web apps six years ago, my perception is that today they have an aspect of multi-faceted apps. Html is just one of the multiple supported outputs of resource-based web sites. They expose services that can be used by your mother or another service. Twitter and Facebook are the greatest examples.

Bringing that to our work and especially the MS platform is somewhat puzzling. Who wants to maintain two entry points? Why a web app and a WCF Soap/Rest interface? Why it’s so unnatural to deal with syndication on web apps?

 

The reuse dilemma

Reuse has always been an OOP challenge. Many programming practices support designs that yield subsystems (size/complexity can vary) that can be reused. Not too many programmers embrace those programming practices, though.

As the complexity of web applications grow we see subteams owing subsystem with the same web application. Their technological choices are restricted by the common denominator. There ought to be a solution for this.

 

MonoRail 3.0

This and other interesting discussions are taking place with the Castle team. I try hard to influence them over the big picture – it’s easy to get distract by what seems to be cool and interesting but deliver no value. In the last two months I drafted and propose a new enhanced design that should deal with the common challenges of web apps of today – and hopefully of tomorrow! Today I completed a working prototype.

 

Minimal core

The core is based on MicroKernel pattern. It’s a truly example of Open-Closed principle. It works by orchestrating a minimal set of extension points. Those are called primitives as they represent core abstract concepts.

The core is split into three architecture layers:

Layer 1: ASP.NET core augmentation

The layer 1 replaces the HttpHandler and HttpModule in ASP.NET with composable equivalents. You can then implement a new “handler” that has “dependencies”, and be sure that those will be satisfied.

Layer 2: Orchestrator

Layer 2 defines a minimal set of primitives and pipeline execution process. It establishes the minimal policy (behavior) but does not make assumptions over the implementation – remember the Dependency Inversion Principle?

Layer 3: Model-View-Controller

Finally, the third layer is an implementation of layer 2 that exposes the common behavior of Model-View-Controller we all know and love. It also exposes extension points, such as an execution sink for controller execution.

 

Side-by-side extensions

Windsor turned out to be successful because it delivered a rich extensibility mechanism and a minimal but useful combination of default behaviors. MonoRail 3 is built with the same principles. In fact, its Model-View-Controller capabilities are just one implementation over a set of “primitive” contracts. Behavior can be modified, added or removed by using a small set of extension points.

The design supports side-by-side extensions, which means that extensions do not replace one-another, but instead are always additive. For example, I can have a WindsorIntegration and AutofacIntegration running at the same time. I can add to the mix Razor View Engine and IronRuby support. Not a single line of configuration code or xml.

 

Composition by default, even in your code

Yes, you can turn off or replace it, but by default your app will have an IoC Container (well, MEF) composing your controllers. The composition is not limited to your types, in fact, you can express dependencies over framework components and request level objects.

Maximized simplicity

The following is a valid controller:

public class ProductsController
{
    public ActionResult Index()
    {
        var products = // fetch list
        return new ViewResult() { Model = products };
    }

    [RespondTo(ContentType.Html|ContentType.Xml|ContentType.JSon)]
    public Product View(int id)
    {
        var product = // fetch by id
        
        if (product == null)
            throw new HttpException(404, "product not found");
            
        return product;
    }
    
    public Product New()
    {
        return new Product();
    }

    public ActionResult Create(Product product)
    {
        // pretend to save
        var product = new Product();
        
        return RespondTo( format => 
            format.Model(product).
              Html().
              Xml( new ViewResult("create.xml") ).
              Json()
        );
    }
    
}

If access to some response, request (or similar) objects are necessary, no worry, you have two options: use the Controller base class or specify the dependencies in your constructor.

Powered by MEF

One of my goals is to demonstrate how MEF can be used to enhance your frameworks, instead of just your applications. By using MEF I could easily skip any “registration” step usually required by typical IoC Containers. I can also discover extensions easily in runtime without extra code.


Where/When?

I’m planning to release a first drop later this week. Note I’m kinda extra busy as I’m getting married next weekend, but watch out for a preview drop.

Integrating MonoRail with your favorite IoC container

September 5th, 2008

I’m way outdated on my e-mail-reading and especially blog-reading. I don’t even read them anymore! I quickly scan them and try to get a gist… Someday people will actually emphasizes some words to make it easier for scanners like me to get the idea without stopping and reading every word ;-)

Anyway, I bumped into one of Jeremy’s post. Quoting:

“When we were deciding between Ruby on Rails, the ASP.Net MVC, and MonoRail for our project architecture in June, I dismissed MonoRail in small part because I didn’t want to be forced to use Windsor as our IoC tool (for some reason).”

Well, MR in no way forces you to use Windsor. For goodness’ sake, it’s on our mission page:

Castle should not be all-or-nothing. The developer can use the tools he wants to use, and at the same time, use different approaches in different areas of his application in a peaceful manner.

Of course, MR magically integrates with Windsor – what would you expect from us? But it can, just as well, magically integrates with any IoC container too.

So, what does it take to integrate MonoRail with your IoC container of choice?

First thing: MonoRail is made of several services. It had always used a composition-over-inheritance design principle that someone day more people will understand and adopt more – we’re always a decade behind, aren’t we?

(note to self: blog about all services that make the whole monster live).

So basically all you need to do is replace one or two services, depending on the level of integration you want. For the most basic integration, you might want to replace the controller factory and the filter factory by services implementation that know your IoC container (and knows how to access an instance of it). This can be made through the external monorail configuration (on the web.config) as described on the services article and on the configuration documentation.

A more complete level of integration, however, is something faily recent (10 months old I guess). Quoting an old post:

MonoRail now always uses the ServiceProviderLocator class to obtain a IServiceProvider and uses it as it’s parent container. That’s means that you can use any IoC container by simply making your HttpApplication class implement IServiceProvider (or better, IServiceProviderEx).

That means that MonoRail will always ask your code (the class that extends HttpApplication and is set on global.asax) before adding its default implementation of any of its services. That makes trivial to replace any service.

Note: I was actually going to provide a sample code but sorry, no time…

MonoRail marches into the cloud

September 1st, 2008

David is blogging about his experience with Amazon EC2. As you might know the images you can apply on a EC2 machine are all linux based. That didn’t stop him. He went on with Mono and MonoRail and got it working there. That certainly put more pressure on Castle community to get a bit more Mono-friendly/driven code. Now, if only the mono people could offer some help…

My first and last experience with EC2 was java based, and man, painful. The pain that only java can deliver. :-)

Poor man’s usability test

July 3rd, 2008

Going public with donjon was a great decision. We got several levels of feedback, and not all of them are conscious or direct. Let me go over some of these:

Exceptions

First of all, we use MonoRail Exception Chaining extension and get e-mail with all exception details, plus the page, form, query string, session and flash state, so it’s relatively easy figuring out how to reproduce the situation that caused the exception. This approach wont send us only unhandled exceptions, instead we use RegisterExceptionAndNotifyExtensions to make sure we get it. The following is a typical donjon’s action in a controller

[return: JSONReturnBinder(Properties = "Id,UserName,FullName,Email")]
[AccessibleThrough(Verb.Post)]
public User[] AddMembers(string key, string[] users)
{
    try
    {
        ...
    }
    catch(Exception e)
    {
        RegisterExceptionAndNotifyExtensions(e);
        Logger.Error("AddMembers failed", e);
        throw;
    }
}

RegisterExceptionAndNotifyExtensions will make sure the chain is going to be executed. The Logger is our ultimate place to detect problems, finally we throw so the ajax call get a status 500. Some places I dont even throw, just set StatusCode to 500 and RenderText(a nice error message)

I also find a best practice to always start writing and testing an action/page with the error handler. So my actions usually starts as this:

public void Action()
{
    try
    {
        throw new Exception("something bad");
    }
    catch(Exception e)
    {
        RegisterExceptionAndNotifyExtensions(e);
    }
}

I find a good practice to assume that at some point something might go wrong, and the user is properly notified. It’s just too much to assume that the action will always be successful.

Settings and defaults

Each user on donjon has a preferences setting. Inspecting the database I found that almost no one ever set a preference. Disturbing to me, as I think the Issue list as it is is just too bloated with information, so the first thing I do is configuring it to show less columns. Nobody did that, possibly because nobody knew how to do it.

Ok, lesson learned and code fixed. donjon will set up an user with an initial preference set to less columns.

Right side Navigation

Aaron complained about this one. It was inspired on some tool I’ve used, so I thought breaking the convention would be a good thing. Bad news to me: “don’t break user expectation” and “don’t try to create new conventions unless they are revolutionary” are some huge bullet points in the book “Prioritizing Web Usability”.

Just to unarguably prove that my decision was dumb, I found the article Navigation: Left is Best

Another lesson learned.

Others

The issue list page was designed and redesigned at least 10 times. All of them functional. The present version is the one that I’m satisfied, but I’m sure there are room for improvements.

I gotta tell you that at first it’s not easy to not to think as a programmer and instead wear the user hat when designing a page. Your programmer’s mind want to make things easier for you (code-wise), your user’s mind wants to make things much more complex. Yeah, sometimes to make the experience simpler you have to write much more code. My guess is that it’s an eternal struggle.

So expect some big improvements for beta 2 :-)

CombineJS ViewComponent

June 27th, 2008

A while ago I added this issue, which is basically a spec for a viewcomponent I urged for, in the hope that someone would face the challenge and, well, just do it. My first thought was that creating something like that would be a bit complex. Here’s the issue description:

The idea is to be able to combine and allow browsers to cache a set of files:

#blockcomponent(JSCombine)
$combiner.add("$siteroot/content/jquery-1.2.3.js")
$combiner.add("$siteroot/content/jquery-someplug.js")
$combiner.add("$siteroot/content/myjs.js")
#end

Which should output something like

592702907bb371_

The hascode should be a composition of the lastmodified of each file's lastmodified attribute, so if a file is changed, the browser will request them again.

There should also be a CssCombine.

The goal is pretty simple: one request and all js is downloaded, hopefully cached, and if some file change a new hash will force the browsers to update their copy.

Today I decided to go on and implement that, was prepared to spend the whole day, but dont know how, was done in less than an hour.

Here the idea:

  1. Collect a list of the files
  2. Calculate a hash based on the last modified date of each file
  3. Create an in-memory aggregation of all files
  4. Register this content within MonoRail static resource service
  5. Output a script tag pointing to the newly created MR resource

And here’s the code that does exactly that:

[ViewComponentDetails("CombineJS")]
public class CombineJSViewComponent : ViewComponent
{
    public override void Render()
    {
        var combiner = new CombinerConfig(AppDomain.CurrentDomain.BaseDirectory);
        PropertyBag["combiner"] = combiner;

        // Evaluate the component body, without output 
        RenderBody(new StringWriter());

        string key = (string) ComponentParams["key"];
        long hash = CalculateChangeSetHash(combiner.Files);

        IStaticResourceRegistry resourceRegistry = EngineContext.Services.StaticResourceRegistry;

        if (!resourceRegistry.Exists(key, null, hash.ToString()))
        {
            var staticContentResource = 
                new StaticContentResource(CombineJSContent(combiner.Files));

            resourceRegistry.RegisterCustomResource(
                key, null, hash.ToString(), staticContentResource, 
                    "application/x-javascript", DateTime.Now);
        }

        string fullName = "/MonoRail/Files/CombinedJS?name=" + key + "&version=" + hash;
        RenderText("<script type=\"text/javascript\" src=\"" + fullName + "\"></script>");
    }

    private string CombineJSContent(IList<string> files)
    {
        StringBuilder sb = new StringBuilder(1024 * files.Count);

        foreach(var file in files)
        {
            using(StreamReader reader = File.OpenText(file))
            {
                sb.Append(reader.ReadToEnd());
            }
            sb.AppendLine();
        }

        return sb.ToString();
    }

    private static long CalculateChangeSetHash(IList<string> files)
    {
        long hash = 0;

        foreach(var file in files)
        {
            if (File.Exists(file))
            {
                DateTime dt = File.GetLastWriteTimeUtc(file);
                hash += dt.Ticks * 37;
            }
        }

        return hash;
    }

    public class CombinerConfig
    {
        private readonly string basePath;
        private readonly List<string> files = new List<string>();

        public CombinerConfig(string basePath)
        {
            this.basePath = basePath;
        }

        public IList<string> Files
        {
            get { return files; }
        }

        public void Add(string jsFile)
        {
            Add(jsFile, null);
        }

        public void Add(string jsFile, IDictionary options)
        {
            files.Add(Path.Combine(basePath, jsFile));
        }
    }
}

And this is how to use it (Nvelocity view engine example)

#blockcomponent(CombineJS with "key=deflayout")
 $combiner.Add("Content/js/jquery/jquery-1.2.6.min.js")
 $combiner.Add("Content/js/jquery/jquery.metadata.js")
 $combiner.Add("Content/js/jquery/jquery.label_over.js")
#end

Note that the key must represent an unique set of files.

Now my plan is to add js minify capabilities, either by selecting the minified file using a naming pattern, or minifying in place.

Where no man has gone before

June 6th, 2008

Bill seems to have guts. He has posted some of his experience with a custom MonoRail + Windsor solution for a b2b app, and seems to have gone deep to customize the way components are resolved to address a business requirement. His point: majority of his clients deal with orders their own way, instead of branching the code or scattering ifs everywhere, he creates a customized component that deal with those requirement, which is automatically selected based on the client accessing the app.

To have that working, he decided to go down and speak with the devil himself. He embraced the use of containers hierarchy.

First of all a disclaimer: the support for parent/child container was added long time ago to MicroKernel/Windsor, really long time, probably in the first commits. But they never went into a _real_ real world testing. Also, I’m not sure the dependency resolution behavior is safe enough. I implemented support for one-way, bottom-up resolution to prevent someone from doing something really bad, but I’m not sure that’s enough. For all these reasons – plus a gut feeling that I shouldn’t have added this concept in the first place – I strongly discourage its use. And that’s why there are no documentation about it on castle web site, no articles (from me at least), and probably no blog posts.

Now if you like sky skiing, drives a motorcycle without helmet, have a compelling reason to use it, then why not give it a try? :-) Bill knows what he’s doing, though, he has contributed patches that demonstrates a deep understanding of the inner workings of castle.

Another idea that I played for a while was the concept of scoped containers for web apps. Mapping containers to the life styles associated with a web app: application, session, request. That would make simple to have components to lifestyles attached to an user session, for instance. However it’s a lot of work and difficult to test. I’m sure it will be available on Windsor/MonoRail 2.0

MR and Windsor set up screencast

May 26th, 2008

Quick, dirty and unrehearsed. Just show how to set up MR without external configuration, how to get Windsor integration enabled and setting up routing. Created to test Screenflow.

Mov file

Autoregistration without Binsor

May 13th, 2008

On my Global.cs I usually have:

private static void RegisterWebComponents()
{
    container.Register(AllTypes.Of<SmartDispatcherController>().
        FromAssembly(typeof(HomeController).Assembly));

    container.Register(AllTypes.Of<ViewComponent>().FromAssembly(typeof(Global).Assembly)
            .Configure(
                delegate(ComponentRegistration reg)
                {
                    reg.Named(reg.ServiceType.Name);
                }));

}

To get Windsor integration:

First, make the Global implement the IContainerAccessor

public class Global : HttpApplication, IContainerAccessor

Then add a static field to hold the container

private static WindsorContainer container;

The App_Start/End and the IContainerAccessor implementation:

protected void Application_Start(object sender, EventArgs e)
{
    container = new WindsorContainer(new XmlInterpreter());
    container.AddFacility("mr", new MonoRailFacility());

    RegisterWebComponents();
}

protected void Application_End(object sender, EventArgs e)
{
    container.Dispose();
}

public IWindsorContainer Container
{
    get { return container; }
}

To Configure MonoRail using code

Make the global implement IMonoRailConfigurationEvents and implement the method Configure:

public class Global : HttpApplication, IContainerAccessor, IMonoRailConfigurationEvents
{
    public void Configure(IMonoRailConfiguration configuration)
    {
        // Configuring ViewEngine
        configuration.ViewEngineConfig.ViewPathRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views");
        configuration.ViewEngineConfig.ViewEngines.Add(new ViewEngineInfo(typeof(NVelocityViewEngine), false));

        // You can configure other things, and hopefully in the future 
        // we can expose a kind of fluent interface to guide you on this process
    }
}