/*
         * /// <summary>
         * /// check authentication attributes for the class
         * /// </summary>
         * protected virtual void MapClassAuth()
         * {
         *  object[] attributes = GetType().GetCustomAttributes(true);
         *  foreach (object attribute in attributes)
         *  {
         *      if (attribute.GetType() == typeof (AuthenticatorAttribute))
         *          AddAuthAttribute(ClassMethodName, attribute);
         *      if (attribute.GetType() == typeof (AuthenticationRequiredAttribute))
         *          AddCheckAuthAttribute(ClassMethodName, attribute);
         *  }
         * }
         */
        /// <summary>
        /// This method goes through all methods in the controller and
        /// add's them to a dictionary. They are later used to invoke
        /// the correct method depending on the url
        /// </summary>
        private void MapMethods()
        {
            lock (_methods)
            {
                // already mapped.
                if (_methods.Count > 0)
                {
                    return;
                }

                object[] controllerNameAttrs = GetType().GetCustomAttributes(typeof(ControllerNameAttribute), false);
                if (controllerNameAttrs.Length > 0)
                {
                    _controllerName = ((ControllerNameAttribute)controllerNameAttrs[0]).Name;
                }
                else
                {
                    _controllerName = GetType().Name;
                    if (ControllerName.Contains("Controller"))
                    {
                        _controllerName = ControllerName.Replace("Controller", "");
                    }
                    _controllerName = ControllerName.ToLower();
                }

                MethodInfo[] methods =
                    GetType().GetMethods(BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance);
                foreach (MethodInfo info in methods)
                {
                    ParameterInfo[] parameters = info.GetParameters();

                    // find regular render methods
                    if (parameters.Length == 0 && info.ReturnType == typeof(string))
                    {
                        string name = info.Name.ToLower();
                        if (name.Length > 3 && (name.Substring(0, 4) == "get_" || name.Substring(0, 4) == "set_"))
                        {
                            continue;
                        }
                        if (name == "tostring")
                        {
                            continue;
                        }

                        // Add authenticators
                        object[] authAttributes = info.GetCustomAttributes(true);
                        foreach (object attribute in authAttributes)
                        {
                            if (attribute.GetType() == typeof(AuthRequiredAttribute))
                            {
                                _authMethods.Add(info.Name.ToLower(), ((AuthRequiredAttribute)attribute).Level);
                            }
                        }
                        _methods.Add(info.Name.ToLower(), info);
                    }

                    // find raw handlers
                    object[] attributes = info.GetCustomAttributes(typeof(RawHandlerAttribute), true);
                    if (attributes.Length >= 1 && info.ReturnType == typeof(void) && parameters.Length == 0)
                    {
                        // Add authenticators
                        object[] authAttributes = info.GetCustomAttributes(true);
                        foreach (object attribute in authAttributes)
                        {
                            if (attribute.GetType() == typeof(AuthRequiredAttribute))
                            {
                                _authMethods.Add(info.Name.ToLower(), ((AuthRequiredAttribute)attribute).Level);
                            }
                        }
                        _binaryMethods.Add(info.Name.ToLower(), info);
                    }
                } //foreach

                methods = GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic);
                foreach (MethodInfo info in methods)
                {
                    ParameterInfo[] parameters = info.GetParameters();

                    // find before filters.
                    if (parameters.Length == 0 && info.ReturnType == typeof(bool))
                    {
                        object[] authAttributes = info.GetCustomAttributes(true);
                        foreach (object attribute in authAttributes)
                        {
                            if (attribute.GetType() == typeof(AuthValidatorAttribute))
                            {
                                if (_authValidator != null)
                                {
                                    throw new InvalidOperationException("Auth validator have already been specified.");
                                }
                                _authValidator = info;
                            }
                            else if (attribute.GetType() == typeof(BeforeFilterAttribute))
                            {
                                BeforeFilterAttribute       attr = (BeforeFilterAttribute)attribute;
                                LinkedListNode <MethodInfo> node = new LinkedListNode <MethodInfo>(info);


                                if (attr.Position == FilterPosition.First)
                                {
                                    _beforeFilters.AddFirst(node);
                                }
                                else if (attr.Position == FilterPosition.Last)
                                {
                                    _beforeFilters.AddLast(node);
                                }
                                else
                                {
                                    if (_lastMiddleFilter == null)
                                    {
                                        _beforeFilters.AddLast(node);
                                    }
                                    else
                                    {
                                        _beforeFilters.AddAfter(_lastMiddleFilter, node);
                                    }

                                    _lastMiddleFilter = node;
                                }
                            }
                        }
                    }
                }

                // Map index method.
                MethodInfo mi = GetType().GetMethod("Index", BindingFlags.Public | BindingFlags.Instance);
                if (mi != null && mi.ReturnType == typeof(string) && mi.GetParameters().Length == 0)
                {
                    DefaultMethod = "Index";
                }
            }
        }
        /// <summary>
        /// Method that calls a method of an application.
        /// </summary>
        /// <param name="currentType">Type of the application.</param>
        /// <param name="request">Request object to send to application.</param>
        /// <param name="aux">Auxiliar object that the application may need as utility.</param>
        /// <returns>Response by the application.</returns>
        public ActionResult CallAction(Type currentType, object request, object context, object aux)
        {
            var  assembly = currentType.Assembly;
            Type type     = null;

            if (ControllerName == null)
            {
                return(null);
            }

            foreach (Type t in assembly.GetTypes())
            {
                if (t.Name.ToLower().Equals(ControllerName.ToLower() + "controller"))
                {
                    type = t;
                    break;
                }
            }

            if (type == null)
            {
                return(new Controller().NotFoundResult("Controller not Found."));
            }

            var instance = Activator.CreateInstance(type);

            Console.WriteLine("   + Controller: {0}", instance.GetType().ToString());
            ((Controller)instance).Request = request;
            ((Controller)instance).Context = context;
            ((Controller)instance).Aux     = null;
            if (aux != null)
            {
                ((Controller)instance).Aux = aux;
            }


            if (ActionName == null)
            {
                return(new Controller().NotFoundResult("No action specified."));
            }

            Type httpMethodType;

            MethodInfo[] methodInfos = instance.GetType().GetMethods();

            foreach (var m in methodInfos)
            {
                _methodAttributes.TryGetValue(((HttpRequest)request).HttpMethod, out httpMethodType);
                //if (m.GetCustomAttributes(typeof(HttpGET), true).Length > 0)
                //    Console.WriteLine("Method: " + m.Name);
                if (m.Name.ToLower().Equals(ActionName.ToLower()))//m.GetCustomAttributes(_methodAttributes., true))
                {
                    if (m.GetCustomAttributes(httpMethodType, true).Length > 0)
                    {
                        Console.WriteLine("   + Action: [{0}] {1}", httpMethodType.Name, m.Name);
                        return((ActionResult)m.Invoke(instance, null));
                    }
                }
            }

            return(new Controller().NotFoundResult("Action not Found."));
        }
 public override int GetHashCode()
 {
     return(ControllerName.ToLower().GetHashCode() ^
            ViewName.ToLower().GetHashCode());
 }