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

Rango.import("mixins/controller")

module Rango
  class Controller
require "rango/rack/request"
    include Rango::ControllerMixin
    include Rango::Templates::TemplateHelpers

    extend Rango::Router::Dispatcher

    class << self
      # @since 0.0.2
      attribute :before_filters, Hash.new
    extend Forwardable
    # for routers
    def self.dispatcher(action)
      lambda do |env|
        Rango.logger.info("Dispatching to #{self}##{action} [#{env["REQUEST_METHOD"]} #{env["PATH_INFO"]}]")
      attribute :autorendering, false

      def inherited(subclass)
        Rango.logger.debug("Inheritting filters from #{self.inspect} to #{subclass.inspect}")
        subclass.before_filters = self.before_filters
        subclass.after_filters = self.after_filters
        subclass.autorendering = self.autorendering
      end

    end

    def run_action
      if self.respond_to?(self.action)
        self.invoke_action(self.action)
      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)
      # [master] Change Merb::Controller to respond to #call and return a Rack Array. (wycats)http://rubyurl.com/BhoY
      # @since 0.0.2
      def call(env)
        self.set_rack_env(env)
        request = Rango::Request.new(env)
        options = env["rango.router.params"]
        method = options[:action] || :index
        response = Rack::Response.new
        controller = self.new(request, options.merge(request.params))

    def to_response
      self.run_action
      #self.response.finish # do we need this?
      [response.status, response.headers, [response.body]] # this way we got real body rather than response object
    rescue Redirection => redirection
      redirection.to_response
    rescue HttpError => exception
      self.rescue_http_error(exception)
    rescue Exception => exception # so we can be sure that all the exceptions which occures in controller can be captured by rescue_http_error method
      if Rango.development? or Rango.testing?
        raise exception
      else
        message = "#{exception.class}: #{exception.message}"
        server_error = InternalServerError.new(message)
        server_error.backtrace = caller
        self.rescue_http_error(server_error)
        response.status = controller.status if controller.status
        response.headers.merge!(controller.headers)
        return response.finish
      end

      # @experimental
    end

    # @since 0.0.2
    # @version 0.2.1
    # @return [String] Escaped URL (which is RFC recommendation)
        Rango::Router::Dispatcher.route_to(env, self)
      end

      def proceed_value(value)
        case value
        when true, false then value.to_s
    attr_reader :env
    def initialize(env)
      @env = env
    end

    def request
      @request ||= Rango::Request.new(env)
    end

    def response
      @response ||= Rack::Response.new
    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> Support for more advanced exceptions handling, updates to new dispatcher

<DFF> @@ -1,6 +1,7 @@
 # encoding: utf-8
 
 Rango.import("mixins/controller")
+Rango.import("helpers")
 
 module Rango
   class Controller
@@ -8,8 +9,6 @@ module Rango
     include Rango::ControllerMixin
     include Rango::Templates::TemplateHelpers
 
-    extend Rango::Router::Dispatcher
-
     class << self
       # @since 0.0.2
       attribute :before_filters, Hash.new
@@ -21,9 +20,11 @@ module Rango
       attribute :autorendering, false
 
       def inherited(subclass)
-        Rango.logger.debug("Inheritting filters from #{self.inspect} to #{subclass.inspect}")
-        subclass.before_filters = self.before_filters
-        subclass.after_filters = self.after_filters
+        unless subclass.before_filters.empty? && subclass.after_filters.empty?
+          Rango.logger.debug("Inheritting filters from #{self.inspect} to #{subclass.inspect} (before: #{subclass.before_filters.inspect}, after: #{subclass.after_filters.inspect})")
+          subclass.before_filters = self.before_filters
+          subclass.after_filters = self.after_filters
+        end
         subclass.autorendering = self.autorendering
       end
 
@@ -42,9 +43,9 @@ module Rango
       # [master] Change Merb::Controller to respond to #call and return a Rack Array. (wycats)http://rubyurl.com/BhoY
       # @since 0.0.2
       def call(env)
-        self.set_rack_env(env)
+        Rango::Router.new.set_rack_env(env) # See rango/router/adapters/*
         request = Rango::Request.new(env)
-        options = env["rango.router.params"]
+        options = env["rango.router.params"] || raise("rango.router.params property has to be setup at least to empty hash")
         method = options[:action] || :index
         response = Rack::Response.new
         controller = self.new(request, options.merge(request.params))
@@ -68,6 +69,20 @@ module Rango
         response.status = controller.status if controller.status
         response.headers.merge!(controller.headers)
         return response.finish
+      rescue HttpError => exception
+        rescue_http_error(exception)
+      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)
+        if self.respond_to?(:render_http_error)
+          message = self.render_http_error(exception)
+          exception.message = message unless message.nil?
+        end
+        exception.to_response
       end
 
       # @experimental
@@ -79,6 +94,14 @@ module Rango
         Rango::Router::Dispatcher.route_to(env, self)
       end
 
+      # for routers
+      def self.dispatcher(action)
+        lambda do |env|
+          env["rango.controller.action"] = action
+          return self.call(env)
+        end
+      end
+
       def proceed_value(value)
         case value
         when true, false then value.to_s

Support for more advanced exceptions handling, updates to new dispatcher