public object[] GetArguments(RouteInvocation route, IRequest request, MethodInfo method)
        {
            var foundArgs = new Dictionary<string, string[]>(ParameterComparer);
            foundArgs.Concat(route.RouteData);
            foundArgs.Concat(request.Query);
            foundArgs.Concat(request.Form);

            var args = new List<object>();
            foreach (var parameter in method.GetParameters())
            {
                object arg = null;
                var converter = Converters.FirstOrDefault
                    (x => x.CanConvert(parameter.ParameterType));
                if (converter != null) {
                    arg = converter.Convert(parameter.ParameterType, parameter.Name, foundArgs);
                }
                if ((converter == null || arg == null) && parameter.IsOptional)
                {
                    arg = (parameter.HasDefaultValue ? parameter.DefaultValue : null);
                }

                if (arg != null || parameter.IsOptional)
                {
                    args.Add(arg);
                }
                else
                {
                    throw new InvalidOperationException(String.Format(
                        "Required argument {0} was not supplied to method {1} on controller {2}",
                        parameter.Name, method.Name, method.DeclaringType));
                }
            }

            return args.ToArray();
        }
        public void CanBindRouteDataWithNullOptionalParameters()
        {   
            var data = new Dictionary<string, string>() {
                { "one", "foo" },
                { "two", "bar" }
            };

            var route = new RouteInvocation(null, null, data);
            var request = new Mock<IRequest>();
            request.SetupGet(x => x.Query).Returns(new Dictionary<string, string[]>());

            var method = this.GetType().GetMethod("methodWithNullOptionalParameters",
                BindingFlags.NonPublic | BindingFlags.Instance);

            var result = binder.GetArguments(route, request.Object, method);

            CollectionAssert.AreEqual(new object[] { "foo", "bar", null }, result);
        }
        public void CanBindCompleteTestObject()
        {
            var data = new Dictionary<string, string>() {
                { "intvalue", "1" },
                { "stringvalue", "bar" },
                { "datetimevalue", "2014-01-01" }
            };

            var route = new RouteInvocation(null, null, data);
            var request = new Mock<IRequest>();
            request.SetupGet(x => x.Query).Returns(new Dictionary<string, string[]>());

            var method = this.GetType().GetMethod("testBindingMethod",
                BindingFlags.NonPublic | BindingFlags.Instance);

            var result = binder.GetArguments(route, request.Object, method);
            var obj = result.Single() as TestObject;

            Assert.IsNotNull(obj);
            Assert.AreEqual(1, obj.IntValue);
            Assert.AreEqual("bar", obj.StringValue);
            Assert.AreEqual(new DateTime(2014, 1, 1), obj.DateTimeValue);
        }
        public void CanBindRouteDataWithArrayConversions()
        {
            var data = new Dictionary<string, string[]> {
                { "one", new string[] { "1", "2", "3" } }
            };

            var route = new RouteInvocation(null, null, new Dictionary<string, string>());
            var request = new Mock<IRequest>();
            request.SetupGet(x => x.Query).Returns(data);

            var method = this.GetType().GetMethod("methodWithArrayParameters",
                BindingFlags.NonPublic | BindingFlags.Instance);

            var result = binder.GetArguments(route, request.Object, method);

            var arr1 = result[0] as int[];

            CollectionAssert.AreEqual(new int[] { 1, 2, 3 }, arr1);
        }
        public void CanBindRouteDataWithConversions()
        {
            var data = new Dictionary<string, string>() {
                { "one", "1" },
                { "two", "true" },
                { "three", "deadbeef-face-baba-da1e-cafec0deface" }
            };

            var route = new RouteInvocation(null, null, data);
            var request = new Mock<IRequest>();

            var method = this.GetType().GetMethod("methodWithTypedParameters",
                BindingFlags.NonPublic | BindingFlags.Instance);

            var result = binder.GetArguments(route, request.Object, method);

            CollectionAssert.AreEqual(new object[] { 1, true,
                new Guid ("deadbeef-face-baba-da1e-cafec0deface") }, result);
        }