/// <summary>
        /// Resolves and provides an instance of the specified controller.
        /// </summary>
        /// <param name="request">The request being served.</param>
        /// <param name="controllerName">Name of the controller.</param>
        /// <returns></returns>
        public virtual ControllerFactoryResult CreateController(ResolvedNavigationRequest request, string controllerName)
        {
            Guard.ArgumentNotNull(request, "request");
            Guard.ArgumentNotNullOrEmpty(controllerName, "controllerName");
            
            TraceSources.MagellanSource.TraceVerbose("Resolving controller '{0}' for request '{1}'", controllerName, request);

            controllerName = controllerName.ToUpper(CultureInfo.InvariantCulture);
            if (!controllerBuilders.ContainsKey(controllerName))
            {
                TraceSources.MagellanSource.TraceError("Failed to resolve controller '{0}' for request '{1}'", controllerName, request);
                throw new ArgumentException(string.Format("A controller by the name of '{0}' could not be found. Please ensure the controller has been registered.", controllerName), "controllerName");
            }

            var controller = controllerBuilders[controllerName]();
            return new ControllerFactoryResult(controller, 
                () =>
                    {
                        var disposableController = controller as IDisposable;
                        if (disposableController != null)
                        {
                            TraceSources.MagellanSource.TraceVerbose("The controller '{0}' is disposable, so it is being disposed.", controllerName);
                            disposableController.Dispose();
                        }
                    }
                );
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ControllerContext"/> class.
 /// </summary>
 /// <param name="controller">The controller.</param>
 /// <param name="request">The request.</param>
 /// <param name="viewEngines">The view engines.</param>
 /// <param name="modelBinders"></param>
 /// <param name="releaseCallback">A callback that is invoked when the current request needs to be 
 /// cleaned up.</param>
 public ControllerContext(IController controller, ResolvedNavigationRequest request, ViewEngineCollection viewEngines, ModelBinderDictionary modelBinders, Action releaseCallback)
 {
     this.controller = controller;
     this.request = request;
     this.viewEngines = viewEngines;
     this.modelBinders = modelBinders;
     this.releaseCallback = releaseCallback;
 }
 /// <summary>
 /// Initializes the specified view.
 /// </summary>
 /// <param name="view">The view.</param>
 /// <param name="model">The model.</param>
 /// <param name="request">The request.</param>
 public virtual void Prepare(object view, object model, ResolvedNavigationRequest request)
 {
     CallInitializeMethods(model, request);
     AssignModelToView(view, model);
     AssignNavigator(view, request);
     AssignNavigator(model, request);
     WireUpLoadedEvent(model, view);
 }
        /// <summary>
        /// Processes the navigation request.
        /// </summary>
        /// <param name="request">The navigation request information.</param>
        public void ProcessRequest(ResolvedNavigationRequest request)
        {
            var modelName = request.RouteValues.GetOrDefault<string>("viewModel");
            
            var pair = factory.CreateViewModel(request, modelName);

            initializer.Prepare(pair.View, pair.ViewModel, request);

            request.Navigator.NavigateDirectToContent(pair.View, request);
        }
        /// <summary>
        /// Creates a view and view model to handle the given navigation request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="viewModelName">Name of the view model.</param>
        /// <returns>
        /// An object containing the View/ViewModel pair.
        /// </returns>
        public ViewModelFactoryResult CreateViewModel(ResolvedNavigationRequest request, string viewModelName)
        {
            var name = viewModelName.ToUpper(CultureInfo.InvariantCulture);
            if (!modelBuilders.ContainsKey(name))
            {
                throw new ArgumentException(string.Format("A view model by the name {0} is not registered in this ViewModelFactory.", name));
            }
            
            var model = modelBuilders[name]();
            var view = viewBuilders[name]();

            return new ViewModelFactoryResult(view, model);
        }
 /// <summary>
 /// Resolves and provides an instance of the specified controller.
 /// </summary>
 /// <param name="request">The request being served.</param>
 /// <param name="controllerName">Name of the controller.</param>
 /// <returns></returns>
 public override ControllerFactoryResult CreateController(ResolvedNavigationRequest request, string controllerName)
 {
     var result =  base.CreateController(request, controllerName);
     if (result.Controller is ControllerBase)
     {
         ((ControllerBase) result.Controller).ActionInvoker = new AsyncActionInvoker();
     }
     else
     {
         TraceSources.MagellanSource.TraceVerbose("The AsyncControllerFactory is in use, but the controller '{0}' does not derive from ControllerBase.", controllerName);
     }
     return result;
 }
        /// <summary>
        /// Maps a navigation parameters to target action parameter.
        /// </summary>
        /// <param name="request">The controller context.</param>
        /// <param name="bindingContext">The binding context.</param>
        /// <returns>
        /// The value that will be supplied to the action.
        /// </returns>
        public object BindModel(ResolvedNavigationRequest request, ModelBindingContext bindingContext)
        {
            var requestParameter = bindingContext.RouteValues.FirstOrDefault(x => string.Equals(x.Key, bindingContext.TargetParameterName, StringComparison.InvariantCultureIgnoreCase));
            if (requestParameter.Key == null)
            {
                TraceSources.MagellanSource.TraceError("DefaultModelBinder could not find a parameter '{0}' for the method '{1}' in the list of navigation parameters.", request.RouteValues, bindingContext.TargetParameterName);
                throw new ModelBindingException(bindingContext, request);
            }


            var source = requestParameter.Value;
            var targetType = bindingContext.TargetParameterType;

            return AmazingConverter.Convert(source, targetType);
        }
        private static string BuildMessage(ModelBindingContext context, ResolvedNavigationRequest request)
        {
            var message = new StringBuilder();
            message.AppendFormat(
                "The method '{0}' on target '{1}' requires a parameter named '{2}', which was not supplied.",
                context.TargetMethod.Name,
                context.TargetMethod.DeclaringType.FullName,
                context.TargetParameterName
                );

            message.AppendLine().AppendLine();

            message.Append("Candidate route parameters are:");
            foreach (var key in request.RouteValues.Keys)
            {
                message.AppendLine().Append(" - " + key);
            }
            return message.ToString();
        }
        /// <summary>
        /// Resolves and provides an instance of the specified controller.
        /// </summary>
        /// <param name="request">The request being served.</param>
        /// <param name="controllerName">Name of the controller.</param>
        /// <returns></returns>
        public ControllerFactoryResult CreateController(ResolvedNavigationRequest request, string controllerName)
        {
            var controller = serviceLocator.GetInstance<IController>(controllerName);
            if (isAsync && controller is ControllerBase)
            {
                ((ControllerBase)controller).ActionInvoker = new AsyncActionInvoker();
            }

            return new ControllerFactoryResult(
                controller,
                () =>
                {
                    var disposableController = controller as IDisposable;
                    if (disposableController != null)
                    {
                        disposableController.Dispose();
                    }
                });
        }
        /// <summary>
        /// Processes the navigation request.
        /// </summary>
        /// <param name="request">The navigation request information.</param>
        public void ProcessRequest(ResolvedNavigationRequest request)
        {
            var controllerName = request.RouteValues.GetOrDefault<string>("controller");
            
            request.ReportProgress(new BeginRequestNavigationEvent());
            request.ReportProgress(new ResolvingControllerNavigationEvent());
            var controllerLease = controllerFactory.CreateController(request, controllerName);
            var controller = controllerLease.Controller;

            controller.Execute(
                new ControllerContext(
                    controllerLease.Controller, 
                    request, 
                    viewEngines,
                    modelBinders,
                    () =>
                        {
                            controllerLease.Dispose();
                            request.ReportProgress(new CompleteNavigationEvent());
                        }));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ControllerContext"/> class.
 /// </summary>
 /// <param name="controller">The controller.</param>
 /// <param name="request">The request.</param>
 /// <param name="viewEngines">The view engines.</param>
 public ControllerContext(IController controller, ResolvedNavigationRequest request, ViewEngineCollection viewEngines)
     : this(controller, request, viewEngines, null, null)
 {
 }
 public ControllerFactoryResult CreateController(ResolvedNavigationRequest request, string controllerName)
 {
     var controller = _container.Resolve<IController>(controllerName);
     return new ControllerFactoryResult(controller, null);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ModelBindingException"/> class.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="request">The request.</param>
 public ModelBindingException(ModelBindingContext context, ResolvedNavigationRequest request)
     : base(BuildMessage(context, request))
 {
 }
        /// <summary>
        /// If the target implements <see cref="INavigationAware"/>, assigns the Navigator to it, and sets 
        /// the NavigationProperties.Navigator attached property.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="request">The request.</param>
        protected virtual void AssignNavigator(object target, ResolvedNavigationRequest request)
        {
            if (target == null)
                return;

            var navigator = request.Navigator;
            if (navigator == null) 
                return;
            
            var navigationAware = target as INavigationAware;
            var dependencyObject = target as DependencyObject;

            if (navigationAware != null)
            {
                TraceSources.MagellanSource.TraceVerbose("The object '{0}' implements the INavigationAware interface, so it is being provided with a navigator.", navigationAware.GetType().Name);
                navigationAware.Navigator = navigator;
            }

            if (dependencyObject != null)
            {
                NavigationProperties.SetNavigator(dependencyObject, navigator);
                NavigationProperties.SetCurrentRequest(dependencyObject, request);
            }
        }
        /// <summary>
        /// Discovers and invokes any Initialize methods according to the initializeMethodSelector passed to 
        /// the constructor.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="request">The request.</param>
        protected virtual void CallInitializeMethods(object model, ResolvedNavigationRequest request)
        {
            if (model == null || initializeMethodSelector == null)
                return;

            var initializers = model.GetType().GetMethods() as IEnumerable<MethodInfo>;
            var initializer = initializeMethodSelector(initializers);
            if (initializer == null)
            {
                return;
            }

            var arguments = new List<object>();
            foreach (var parameterInfo in initializer.GetParameters())
            {
                var bindingContext = new ModelBindingContext(parameterInfo.Name, initializer, parameterInfo.ParameterType, request.RouteValues);
                var binder = modelBinders.GetBinder(parameterInfo.ParameterType);
                var argument = binder.BindModel(request, bindingContext);
                arguments.Add(argument);
            }

            initializer.Invoke(model, arguments.ToArray());
        }
        public void ProcessRequest(ResolvedNavigationRequest request)
        {

        }