/// <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> /// 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> /// 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; } }
/// <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> /// 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()); }