<NME> controller.rb
<BEF> # encoding: utf-8

class Rango
  class Controller
    # @since 0.0.1
    # @return [Rango::Request]
    # @see Rango::Request
      else
        raise NotFound, "Controller #{self.class.name} doesn't have method #{self.action}"
      end
    end

    # default, redefine in plugin if you need to
    def invoke_action(action)
    # @return [Rango::Logger] Logger for logging project related stuff.
    # @see Rango::Logger
    attribute :logger, Project.logger
  end
end
    end

    def_delegators :request, :cookies, :session

    def router_params
      @router_params ||= self.env["rango.router.params"]
    end

    def params
      @params ||= begin
        params = self.request.params
        params.merge!(self.router_params) if router_params
        params
      end
    end

    # redefine this method for your controller if you want to provide custom error pages
    # returns response array for rack
    # if you need to change just body of error message, define render_http_error method
    # @api plugin
    def rescue_http_error(exception)
      # we need to call it before we assign the variables
      body = self.render_http_error(exception)
      [exception.status, exception.headers, body]
    end

    def render_http_error(exception)
      exception.headers["Content-Type"] = "text/html"
      if Rango.production?
        <<-EOF
<h1>Application Error</h1>
<p>
  The application you are trying to reach has currently some issues. Please contact our team and tell us about the troubles. Thank you.
</p>
        EOF
      else
        <<-EOF
<h1>#{exception.class}: #{exception.message}</h1>
<ul>
  <li>#{exception.backtrace.join("</li><li>")}</li>
</ul>
        EOF
      end
    end
  end
end

<MSG> Filters support, Haml rendering works, render & display methods.

<DFF> @@ -2,6 +2,34 @@
 
 class Rango
   class Controller
+    include Rango::HttpExceptions
+    class << self
+      attribute :before_filters, Hash.new
+      attribute :after_filters,  Hash.new
+      # before :login
+      # before :login, :actions => [:send]
+      def before(action, options = Hash.new)
+        self.before_filters[action] = options
+      end
+      
+      def after(action, options = Hash.new)
+        self.after_filters[action] = options
+      end
+      
+      def run(request, params, method, *args)
+        controller = self.new
+        controller.request = request
+        controller.params  = params
+        controller.run_filters(:before, method)
+        value = controller.method(method).call(*args)
+        controller.run_filters(:after, method)
+        return value
+      end
+      
+      def get_filters(type)
+        self.instance_variable_get("@#{type}_filters")
+      end
+    end
     # @since 0.0.1
     # @return [Rango::Request]
     # @see Rango::Request
@@ -15,5 +43,76 @@ class Rango
     # @return [Rango::Logger] Logger for logging project related stuff.
     # @see Rango::Logger
     attribute :logger, Project.logger
+    
+    def find_template(template)
+      Project.settings.template_dirs.each do |directory|
+        path = File.join(directory, template)
+        if File.exist?(path)
+          return path
+        elsif first = Dir["#{path}.*"].first
+          return first
+        end
+      end
+      return nil
+    end
+
+    # TODO: default option for template
+    def render(template)
+      path = self.find_template(template)
+      self.template_engine.render(File.new(path), self)
+    end
+    
+    def template_engine
+      # TODO: test if Project.settings.template_engine nil => useful message
+      # TODO: maybe more template engines?
+      engine_name = Project.settings.template_engine
+      Rango.import("templates/adapters/#{engine_name}.rb")
+      engine_class = Rango::Template.engine(engine_name)
+      engine_class.new
+    rescue LoadError
+      Rango.logger.fatal("Template engine #{engine_name} can't be loaded.")
+      raise Error406.new(self.params)
+    end
+    
+    # TODO: default option for template
+    def display(object, template)
+      render(template)
+    rescue Error406
+      # TODO: provides API
+      format = Project.settings.mime_formats.find do |format|
+        object.respond_to?("to_#{format}")
+      end
+      format ? object.send("to_#{format}") : raise(Error406.new(self.params))
+    end
+    
+    # TODO
+    def messages
+      self.params[:messages]
+    end
+
+    # TODO
+    def redirect(url)
+    end
+    
+    # TODO
+    def cookies
+    end
+
+    # TODO
+    def session
+    end
+    
+    def run_filters(name, method)
+      self.class.get_filters(name).each do |filter_method, options|
+        begin
+          unless options[:except] && options[:except].include?(method)
+            self.send(filter_method)
+          end
+        rescue SkipFilter
+          Rango.logger.debug("Skipping #{name} filter")
+          next
+        end
+      end
+    end
   end
 end

Filters support, Haml rendering works, render & display methods.