예제 #1
0
        /// <summary>
        /// Maps a navigation parameters to target action parameter.
        /// </summary>
        /// <param name="controllerContext">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(ControllerContext controllerContext, 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 action method '{1}' in the list of navigation parameters.", controllerContext.ActionName, bindingContext.TargetParameterName);
                throw new ArgumentException(string.Format("The action '{0}' on controller '{1}' requires a parameter named '{2}', which was not supplied.",
                    controllerContext.ActionName,
                    controllerContext.Controller.GetType().FullName,
                    bindingContext.TargetParameterName));
            }

            var source = requestParameter.Value;
            if (source == null)
            {
                TraceSources.MagellanSource.TraceWarning("The parameter '{0}' which was supplied to action '{1}' was null, but the parameter is declared as type '{2}', which is a value type. DefaultModelBinder is creating a new default instance of the type instead.",
                    bindingContext.TargetParameterName,
                    controllerContext.ActionName,
                    bindingContext.TargetParameterType
                    );

                return bindingContext.TargetParameterType.IsValueType
                    ? Activator.CreateInstance(bindingContext.TargetParameterType)
                    : null;
            }

            if (bindingContext.TargetParameterType.IsAssignableFrom(source.GetType()))
            {
                return source;
            }
            return Convert.ChangeType(source, bindingContext.TargetParameterType, CultureInfo.InvariantCulture);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ChildWindowViewEngineResult"/> class.
 /// </summary>
 /// <param name="viewActivator">The view activator.</param>
 /// <param name="type">The type.</param>
 /// <param name="options">The options.</param>
 /// <param name="controllerContext">The controller context.</param>
 public ChildWindowViewEngineResult(IViewActivator viewActivator, Type type, ViewResultOptions options, ControllerContext controllerContext)
     : base(controllerContext, options)
 {
     _viewActivator = viewActivator;
     _type = type;
     _options = options;
 }
 private static MethodInfo SelectBestActionMethod(ControllerContext controllerContext, string actionName)
 {
     var type = controllerContext.Controller.GetType();
     var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
     var candidateMethods = methods.Where(x => HasMatchingSignature(x, actionName)).ToList();
     if (candidateMethods.Count == 1)
     {
         var result = candidateMethods.First();
         TraceSources.MagellanSource.TraceVerbose("DefaultActionInvoker found the action '{0}' as method '{1}'", actionName, result);
         return result;
     }
     if (candidateMethods.Count > 1)
     {
         var result = candidateMethods
             .OrderBy(x => x.GetParameters().Length)
             .LastOrDefault(
                 candidate => candidate.GetParameters().Select(x => x.Name)
                     .HasSameItemsRegardlessOfSortOrder(controllerContext.Request.RouteValues.Select(x => x.Key))
             );
         TraceSources.MagellanSource.TraceVerbose("DefaultActionInvoker found multiple methods for the action '{0}'. The method selected was '{1}'.", actionName, result);
         return result;
     }
     TraceSources.MagellanSource.TraceError("DefaultActionInvoker could not find a method for the action '{0}'.", actionName);
     return null;
 }
예제 #4
0
 /// <summary>
 /// When implemented in a derived class, allows the derived class to restrict the criteria used to select potential types.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="options">The view parameters.</param>
 /// <param name="viewName">Name of the view.</param>
 /// <param name="candidates">The list of candidate types.</param>
 /// <returns></returns>
 protected override IEnumerable<Type> FilterCandidateTypes(ControllerContext controllerContext, ViewResultOptions options, string viewName, IEnumerable<Type> candidates)
 {
     if (options.GetRegionName() != null || options.GetRegion() != null)
     {
         return candidates.Where(type => typeof (UIElement).IsAssignableFrom(type));
     }
     return new Type[0];
 }
        /// <summary>
        /// When implemented in a derived class, resolves an action by the given name on the controller.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionName">Name of the action.</param>
        /// <returns>
        /// An implementation of <see cref="IActionDescriptor"/>, or null if no action could be found.
        /// </returns>
        protected override IActionDescriptor FindAction(ControllerContext controllerContext, string actionName)
        {
            Guard.ArgumentNotNull(controllerContext, "controllerContext");
            Guard.ArgumentNotNullOrEmpty(actionName, "actionName");

            var method = SelectBestActionMethod(controllerContext, actionName);
            return method == null ? null : new DelegateActionDescriptor(method, controllerContext.Controller);
        }
예제 #6
0
 /// <summary>
 /// When implemented in a derived class, performs the bulk of the action rendering.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 protected override void ExecuteInternal(ControllerContext controllerContext)
 {
     TraceSources.MagellanSource.TraceInformation("The StartProcessResult is launching the process '{0}'.", startInfo.FileName);
     StartedProcess = Process.Start(startInfo);
     if (waitForExit)
     {
         TraceSources.MagellanSource.TraceInformation("The StartProcessResult is waiting for the process '{0}' to exit.", startInfo.FileName);
         StartedProcess.WaitForExit();
     }
 }
예제 #7
0
        /// <summary>
        /// When implemented in a derived class, performs the bulk of the action rendering.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        protected override void ExecuteInternal(ControllerContext controllerContext)
        {
            TraceSources.MagellanSource.TraceVerbose("The RedirectResult is navigating to the request '{0}'.", NewRequest);

            var dispatcher = controllerContext.Request.Navigator.Dispatcher;
            dispatcher.Dispatch(
                delegate
                {
                    controllerContext.Request.Navigator.Navigate(NewRequest);
                });
        }
 /// <summary>
 /// Given a controller and the start of a namespace, generates a set of combinations where views
 /// may be kept.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="baseNamespace">The base namespace.</param>
 /// <param name="viewName">Name of the view.</param>
 /// <returns>
 /// A collection of possible view namespaces.
 /// </returns>
 public virtual IEnumerable<string> GetNamespaces(ControllerContext controllerContext, string baseNamespace, string viewName)
 {
     return new[]
                {
                    baseNamespace + ".Views." + controllerContext.ControllerName,
                    baseNamespace + ".Views." + viewName,
                    baseNamespace + ".Views." + controllerContext.ControllerName + "." + viewName,
                    baseNamespace + ".Views",
                    baseNamespace + "." + controllerContext.ControllerName,
                    baseNamespace
                };
 }
예제 #9
0
        /// <summary>
        /// When implemented in a derived class, performs the bulk of the action rendering.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        protected override void ExecuteInternal(ControllerContext controllerContext)
        {
            TraceSources.MagellanSource.TraceInformation("BackResult is rendering for request '{0}'. RemoveFromJournal is {1}", controllerContext.Request, removeFromJournal);

            var dispatcher = controllerContext.Request.Navigator.Dispatcher;
            dispatcher.Dispatch(
                delegate
                {
                    var navigationService = controllerContext.Request.Navigator;
                    navigationService.GoBack(removeFromJournal);
                });
        }
예제 #10
0
        /// <summary>
        /// Executes the action result.
        /// </summary>
        /// <param name="controllerContext"></param>
        protected override void ExecuteInternal(ControllerContext controllerContext)
        {
            Guard.ArgumentNotNull(controllerContext, "controllerContext");

            var viewName = this.viewName ?? controllerContext.ActionName;
            ViewEngineResult = viewEngines.FindView(controllerContext, Options, viewName);
            if (ViewEngineResult.Success)
            {
                ViewEngineResult.Render();
            }
            else
            {
                throw new ViewNotFoundException(controllerContext.ControllerName, controllerContext.ActionName, viewName, ViewEngineResult.SearchLocations);
            }
        }
예제 #11
0
        /// <summary>
        /// When implemented in a derived class, finds all pre and post <see cref="IResultFilter">result filters</see> that apply to the given action.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionName">Name of the action.</param>
        /// <returns></returns>
        protected override IEnumerable<IResultFilter> FindResultFilters(IActionDescriptor action, ControllerContext controllerContext, string actionName)
        {
            Guard.ArgumentNotNull(action, "action");
            Guard.ArgumentNotNull(controllerContext, "controllerContext");
            Guard.ArgumentNotNullOrEmpty(actionName, "actionName");
            Guard.ArgumentIsOfType(action, typeof(DelegateActionDescriptor), "action");

            var delegateDescriptor = (DelegateActionDescriptor)action;
            var attributeSources = new ICustomAttributeProvider[] { delegateDescriptor.Method, controllerContext.Controller.GetType() };
            var filters = attributeSources.SelectMany(x => x.GetCustomAttributes(true)).Select(x => x as IResultFilter).Where(x => x != null).ToList();
            TraceSources.MagellanSource.TraceVerbose("DefaultActionInvoker found the following result filters for action '{0}': '{1}'.", actionName, 
                string.Join(", ", filters.Select(x => x.GetType().Name).ToArray())
                );
            return filters;
        }
예제 #12
0
 /// <summary>
 /// Executes the action on the specified controller.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="actionName">Name of the action.</param>
 /// <param name="modelBinders">The model binders.</param>
 public override void ExecuteAction(ControllerContext controllerContext, string actionName, ModelBinderDictionary modelBinders)
 {
     var dispatcher = controllerContext.Request.Navigator.Dispatcher;
     ThreadPool.QueueUserWorkItem(
         delegate
             {
                 Thread.CurrentThread.Name = string.Format("Navigation request: {0}", controllerContext.Request);
                 try
                 {
                     ExecuteBase(controllerContext, actionName, modelBinders);
                 }
                 catch (Exception ex)
                 {
                     var rethrower = new Rethrower(
                         string.Format("An exception occurred when attempting to asynchronously execute the request '{0}'. {1}", controllerContext.Request, ex.Message), 
                         ex);
                     dispatcher.Dispatch(rethrower.RethrowOnDispatchThread);
                 }
             });
 }
예제 #13
0
        protected ViewEngineResult FindViewForController(string controllerName, string viewName, object viewParameters)
        {
            var controllerType = Project.Assembly.GetType(controllerName, true);
            var controllerShortName = Path.GetExtension(controllerName.Replace("Controller", "")).Substring(1);

            var context = new ControllerContext(Activator.CreateInstance(controllerType) as IController, 
                new ResolvedNavigationRequest(
                    new Uri("magellan://foobar"),
                    "foobar",
                    true,
                    new Mock<INavigator>().Object, 
                    new Mock<IRoute>().Object, 
                    new RouteValueDictionary(new{controller = controllerShortName, action = "x"}), 
                    new List<INavigationProgressListener>()
                    ), 
                    ViewEngines.CreateDefaults());
            var viewEngine = _viewEngineCreator();
            
            return viewEngine.FindView(context, new ViewResultOptions(viewParameters), viewName);
        }
        /// <summary>
        /// Executes the action on the controller using the parameters and model binders in the current request.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="modelBinders">The model binders.</param>
        /// <returns>
        /// The <see cref="ActionResult"/> returned by the controller action.
        /// </returns>
        public ActionResult Execute(ControllerContext controllerContext, ModelBinderDictionary modelBinders)
        {
            var arguments = new List<object>();
            foreach (var parameterInfo in method.GetParameters())
            {
                var bindingContext = new ModelBindingContext(parameterInfo.Name, Method, parameterInfo.ParameterType, controllerContext.Request.RouteValues);
                var binder = modelBinders.GetBinder(parameterInfo.ParameterType);
                var argument = binder.BindModel(controllerContext.Request, bindingContext);
                arguments.Add(argument);
            }

            try
            {
                var wrapper = DelegateInvoker.CreateInvoker(controller, method);
                return (ActionResult) wrapper.Call(arguments.ToArray());
            }
            catch (Exception ex)
            {
                TraceSources.MagellanSource.TraceError(ex, "The action '{0}' on controller '{1} threw an exception.", controllerContext.ActionName, controllerContext.ActionName);
                throw;
            }
        }
예제 #15
0
        private ActionResult ExecuteAction(ControllerContext controllerContext, ModelBinderDictionary modelBinders, string actionName, IActionDescriptor actionDescriptor)
        {
            var filters = FindActionFilters(actionDescriptor, controllerContext, actionName);
            var result = ExecutePreActionFilters(controllerContext, modelBinders, filters);

            // If one of the filters gave us a result, we can short-circuit calling the action and skip ahead
            if (result != null)
                return result;

            controllerContext.Request.ReportProgress(new ExecutingActionNavigationEvent());

            try
            {
                // Invoke the action on the controller
                result = actionDescriptor.Execute(controllerContext, modelBinders);
            }
            catch (Exception ex)
            {
                // Give post-filters a chance to suppress or handle the exception
                var errorFilterResult = ExecutePostActionFilters(controllerContext, result, ex, filters);
                
                if (errorFilterResult.ExceptionHandled || errorFilterResult.Exception == null)
                    return errorFilterResult.Result;

                if (ex == errorFilterResult.Exception)
                    throw;

                throw errorFilterResult.Exception;
            }

            // Give post-filters a chance rewrite the result
            var filterResult = ExecutePostActionFilters(controllerContext, result, null, filters);
            if (filterResult.ExceptionHandled || filterResult.Exception == null)
                return filterResult.Result;

            throw filterResult.Exception;
        }
예제 #16
0
        /// <summary>
        /// Executes the action on the specified controller.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionName">Name of the action.</param>
        /// <param name="modelBinders">The model binders.</param>
        public virtual void ExecuteAction(ControllerContext controllerContext, string actionName, ModelBinderDictionary modelBinders)
        {
            try
            {
                Guard.ArgumentNotNull(controllerContext, "controllerContext");
                Guard.ArgumentNotNull(modelBinders, "modelBinders");
                Guard.ArgumentNotNullOrEmpty(actionName, "actionName");

                controllerContext.Request.ReportProgress(new ResolvingActionNavigationEvent());
                var actionDescriptor = FindAction(controllerContext, actionName);
                if (actionDescriptor == null)
                {
                    throw new ActionNotFoundException(string.Format("An action by the name '{0}' could not be found on the controller '{1}'. In general, actions should be public instance methods, and should return ActionResult or a derived type. Please ensure the action exists, has a valid signature and the name is spelled correctly.", actionName, controllerContext.Controller.GetType()));
                }

                var actionResult = ExecuteAction(controllerContext, modelBinders, actionName, actionDescriptor);
                ExecuteResult(actionDescriptor, controllerContext, actionName, actionResult);
            }
            finally
            {
                controllerContext.Dispose();
                TraceSources.MagellanSource.TraceInformation("Request completed: '{0}'.", controllerContext.Request);
            }
        }
 private IEnumerable<Type> FindTypesNamed(ControllerContext controllerContext, IEnumerable<string> names)
 {
     var types = GetAllTypesFromAllAssemblies(controllerContext);
     return names.SelectMany(name => types.Where(x => string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase)));
 }
        private IEnumerable<string> CreateShortlistOfNamespacesInWhichToSearch(ControllerContext controllerContext, string view)
        {
            var current = controllerContext.Controller.GetType().Namespace;
            while (current != null && current.Trim().Length > 0)
            {
                foreach (var alternative in NamespaceConvention.GetNamespaces(controllerContext, current, view))
                    yield return alternative;

                var lastDot = current.LastIndexOf('.');
                if (lastDot < 0) break;
                current = current.Substring(0, lastDot);
            }
            yield return null;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ResultExecutingContext"/> class.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="result">The result.</param>
 public ResultExecutingContext(ControllerContext controllerContext, ActionResult result)
 {
     Result = result;
     this.controllerContext = controllerContext;
 }
예제 #20
0
 /// <summary>
 /// When implemented in a derived class, finds all pre and post <see cref="IResultFilter">result filters</see> that apply to the given action.
 /// </summary>
 /// <param name="action">The action.</param>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="actionName">Name of the action.</param>
 /// <returns></returns>
 protected abstract IEnumerable<IResultFilter> FindResultFilters(IActionDescriptor action, ControllerContext controllerContext, string actionName);
예제 #21
0
        /// <summary>
        /// Invokes all post-request filters after the controller has been invoked.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="result">The result.</param>
        /// <param name="ex">The ex.</param>
        /// <param name="filters">The filters.</param>
        /// <returns></returns>
        protected virtual ActionExecutedContext ExecutePostActionFilters(ControllerContext controllerContext, ActionResult result, Exception ex, IEnumerable<IActionFilter> filters)
        {
            controllerContext.Request.ReportProgress(new PostActionFiltersNavigationEvent());

            var executedContext = new ActionExecutedContext(controllerContext, result, ex);
            foreach (var filter in filters)
            {
                filter.OnActionExecuted(executedContext);
            }

            return executedContext;
        }
 private IEnumerable<Type> GetAllTypesFromAllAssemblies(ControllerContext controllerContext)
 {
     var assembly = controllerContext.Controller.GetType().Assembly;
     return assembly.GetTypes().Union(
         additionalViewAssemblies.SelectMany(x => x.GetTypes())
         );
 }
        /// <summary>
        /// Attempts to find the view, or returns information about the locations that were searched.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="options">The view parameters.</param>
        /// <param name="view">The view.</param>
        /// <returns>
        /// A <see cref="ViewEngineResult"/> containing the resolved view or information about the locations that were searched.
        /// </returns>
        public ViewEngineResult FindView(ControllerContext controllerContext, ViewResultOptions options, string view)
        {
            if (!ShouldHandle(controllerContext, options, view))
            {
                return new ViewEngineResult(false, new string[0]);
            }

            var possibleViewNames = NamingConvention.GetAlternativeNames(controllerContext, view);
            var allTypes = FindTypesNamed(controllerContext, possibleViewNames);
            var candidateTypes = FilterCandidateTypes(controllerContext, options, view, allTypes);

            var namespaces = CreateShortlistOfNamespacesInWhichToSearch(controllerContext, view);

            var match = namespaces.Select(ns => FindFirstTypeInNamespace(candidateTypes, ns)).Where(x => x != null).FirstOrDefault();
            if (match != null)
            {
                return CreateViewResult(controllerContext, options, match);
            }

            // Make a list of all search examples used above to create a friendly error message
            var searchAttempts = namespaces.SelectMany(ns => 
                possibleViewNames.Select(name => string.IsNullOrEmpty(ns) 
                    ? string.Format("{0}", name) 
                    : string.Format("{0}.{1}", ns, name)
                    ));

            TraceSources.MagellanSource.TraceInformation("The {0} could not find the view '{1}'. The following locations were searched: \r\n{2}", GetType().FullName, view, string.Join("\r\n- ", searchAttempts.ToArray()));
            return new ViewEngineResult(false, searchAttempts);
        }
 /// <summary>
 /// When implemented in a derived class, allows the derived class to restrict the criteria used to select potential types.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="options">The view parameters.</param>
 /// <param name="viewName">Name of the view.</param>
 /// <param name="candidates">The list of candidate types.</param>
 /// <returns></returns>
 protected abstract IEnumerable<Type> FilterCandidateTypes(ControllerContext controllerContext, ViewResultOptions options, string viewName, IEnumerable<Type> candidates);
 /// <summary>
 /// When implemented in a derived class, indicated whether this view engine should even attempt to 
 /// locate views and handle the request. If this method returns false, no reflection will be 
 /// performed.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="options">The view parameters.</param>
 /// <param name="viewName">Name of the view.</param>
 /// <returns></returns>
 protected virtual bool ShouldHandle(ControllerContext controllerContext, ViewResultOptions options, string viewName)
 {
     return true;
 }
예제 #26
0
 /// <summary>
 /// When implemented in a derived class, resolves an action by the given name on the controller.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="actionName">Name of the action.</param>
 /// <returns>An implementation of <see cref="IActionDescriptor"/>, or null if no action could be found.</returns>
 protected abstract IActionDescriptor FindAction(ControllerContext controllerContext, string actionName);
 /// <summary>
 /// Creates the view result for the specified view type.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="options">The view parameters.</param>
 /// <param name="type">The type.</param>
 /// <returns></returns>
 protected abstract ViewEngineResult CreateViewResult(ControllerContext controllerContext, ViewResultOptions options, Type type);
예제 #28
0
        /// <summary>
        /// Invokes all pre-result filters, before the result has been invoked.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="result">The result.</param>
        /// <param name="resultFilters">The result filters.</param>
        /// <returns></returns>
        protected virtual ResultExecutingContext ExecutePreResultFilters(ControllerContext controllerContext, ActionResult result, IEnumerable<IResultFilter> resultFilters)
        {
            controllerContext.Request.ReportProgress(new PreResultFiltersNavigationEvent());

            var context = new ResultExecutingContext(controllerContext, result);
            foreach (var filter in resultFilters)
            {
                filter.OnResultExecuting(context);
                if (context.Cancel)
                {
                    return context;
                }
            }
            return context;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ResultExecutedContext"/> class.
 /// </summary>
 /// <param name="controllerContext">The controller context.</param>
 /// <param name="result">The result.</param>
 /// <param name="exception">An exception that may have been thrown.</param>
 public ResultExecutedContext(ControllerContext controllerContext, ActionResult result, Exception exception)
 {
     this.result = result;
     Exception = exception;
     this.controllerContext = controllerContext;
 }
예제 #30
0
        /// <summary>
        /// Invokes all pre-request filters, before the controller has been invoked.
        /// </summary>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="modelBinders">The model binders.</param>
        /// <param name="filters">The filters.</param>
        /// <returns></returns>
        protected virtual ActionResult ExecutePreActionFilters(ControllerContext controllerContext, ModelBinderDictionary modelBinders, IEnumerable<IActionFilter> filters)
        {
            controllerContext.Request.ReportProgress(new PreActionFiltersNavigationEvent());

            var context = new ActionExecutingContext(controllerContext, modelBinders);
            foreach (var filter in filters)
            {
                filter.OnActionExecuting(context);
                if (context.OverrideResult != null)
                {
                    return context.OverrideResult;
                }
            }
            return null;
        }