private void Bind(string methodName)
        {
            //创建FormatterParameterBinding对象
            MethodInfo method = typeof(ContactsController).GetMethod(methodName);
            HttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(this.ControllerContext.ControllerDescriptor, method);
            HttpParameterDescriptor parameterDescriptor = actionDescriptor.GetParameters().First();
            MediaTypeFormatter[] formatters = new MediaTypeFormatter[] { new JsonMediaTypeFormatter() };
            FormatterParameterBinding parameterBinding = new FormatterParameterBinding(parameterDescriptor, formatters, null);

            //创建HttpActionBinding并执行
            HttpActionBinding actionBinding = new HttpActionBinding(actionDescriptor,new FormatterParameterBinding[] { parameterBinding });
            HttpActionContext actionContext =new HttpActionContext(this.ControllerContext, actionDescriptor);
            try
            {
                actionBinding.ExecuteBindingAsync(actionContext, CancellationToken.None).Wait();

                //获取绑定参数对象并打印相关数据
                Contact contact = (Contact)actionContext.ActionArguments["contact"];
                Console.WriteLine("{0,-12}: {1}", "Name", contact.Name);
                Console.WriteLine("{0,-12}: {1}", "Phone No.", contact.PhoneNo);
                Console.WriteLine("{0,-12}: {1}", "EmailAddress", contact.EmailAddress);
                Console.WriteLine("{0,-12}: {1}", "Address", contact.Address);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// Update actionBinding to enforce there is at most 1 body parameter. 
        /// If there are multiple, convert them all to <see cref="ErrorParameterBinding"/>
        /// </summary>
        private static void EnsureOneBodyParameter(HttpActionBinding actionBinding)
        {
            IList<HttpParameterDescriptor> parameters = actionBinding.ActionDescriptor.GetParameters();

            int idxFromBody = -1;
            for (int i = 0; i < actionBinding.ParameterBindings.Length; i++)
            {
                if (actionBinding.ParameterBindings[i].WillReadBody)
                {
                    if (idxFromBody >= 0)
                    {
                        // This is the 2nd parameter to read from the body. Flag an error.
                        string name1 = parameters[idxFromBody].ParameterName;
                        string name2 = parameters[i].ParameterName;

                        string message = Error.Format(SRResources.ParameterBindingCantHaveMultipleBodyParameters, name1, name2);
                        actionBinding.ParameterBindings[i] = new ErrorParameterBinding(parameters[i], message);
                        actionBinding.ParameterBindings[idxFromBody] = new ErrorParameterBinding(parameters[idxFromBody], message);
                    }
                    else
                    {
                        idxFromBody = i;
                    }
                }
            }
        }
Example #3
0
            public ActionSelectorCacheItem(HttpControllerDescriptor controllerDescriptor)
            {
                Contract.Assert(controllerDescriptor != null);

                // Initialize the cache entirely in the ctor on a single thread.
                _controllerDescriptor = controllerDescriptor;

                MethodInfo[] allMethods   = _controllerDescriptor.ControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
                MethodInfo[] validMethods = Array.FindAll(allMethods, IsValidActionMethod);

                _combinedCandidateActions = new CandidateAction[validMethods.Length];
                for (int i = 0; i < validMethods.Length; i++)
                {
                    MethodInfo method = validMethods[i];
                    ReflectedHttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(_controllerDescriptor, method);
                    _combinedCandidateActions[i] = new CandidateAction
                    {
                        ActionDescriptor = actionDescriptor
                    };
                    HttpActionBinding actionBinding = actionDescriptor.ActionBinding;

                    // Building an action parameter name mapping to compare against the URI parameters coming from the request. Here we only take into account required parameters that are simple types and come from URI.
                    _actionParameterNames.Add(
                        actionDescriptor,
                        actionBinding.ParameterBindings
                        .Where(binding => !binding.Descriptor.IsOptional && TypeHelper.CanConvertFromString(binding.Descriptor.ParameterType) && binding.WillReadUri())
                        .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName).ToArray());
                }

                _combinedActionNameMapping =
                    _combinedCandidateActions
                    .Select(c => c.ActionDescriptor)
                    .ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);
            }
        public void GetBinding_Invokes_Inner_And_Returns_ActionBinder_With_Tracing_FormatterParameterBinding()
        {
            // Arrange
            Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
            mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));

            Mock<HttpParameterDescriptor> mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
            Mock<FormatterParameterBinding> mockParameterBinding = new Mock<FormatterParameterBinding>(mockParameterDescriptor.Object, new MediaTypeFormatterCollection(), null) { CallBase = true };
            HttpActionBinding actionBinding = new HttpActionBinding(mockActionDescriptor.Object, new HttpParameterBinding[] { mockParameterBinding.Object });

            HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));

            HttpControllerContext controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
            controllerContext.ControllerDescriptor = controllerDescriptor;

            Mock<IActionValueBinder> mockBinder = new Mock<IActionValueBinder>() { CallBase = true };
            mockBinder.Setup(b => b.GetBinding(It.IsAny<HttpActionDescriptor>())).Returns(actionBinding);
            ActionValueBinderTracer tracer = new ActionValueBinderTracer(mockBinder.Object, new TestTraceWriter());

            // Act
            HttpActionBinding actualBinding = ((IActionValueBinder)tracer).GetBinding(mockActionDescriptor.Object);

            // Assert
            Assert.IsAssignableFrom<FormatterParameterBindingTracer>(actualBinding.ParameterBindings[0]);
        }
        private IList<ApiParameterDescription> CreateParameterDescription(HttpActionBinding actionBinding,HttpActionDescriptor actionDescriptor)
        {
            IList<ApiParameterDescription> parameterDescriptions = new List<ApiParameterDescription>();
            // try get parameter binding information if available
            if (actionBinding != null)
            {
                HttpParameterBinding[] parameterBindings = actionBinding.ParameterBindings;
                if (parameterBindings != null)
                {
                    foreach (HttpParameterBinding parameter in parameterBindings)
                    {
                        parameterDescriptions.Add(CreateParameterDescriptionFromBinding(parameter));
                    }
                }
            }
            else
            {
                Collection<HttpParameterDescriptor> parameters = actionDescriptor.GetParameters();
                if (parameters != null)
                {
                    foreach (HttpParameterDescriptor parameter in parameters)
                    {
                        parameterDescriptions.Add(CreateParameterDescriptionFromDescriptor(parameter));
                    }
                }
            }

            return parameterDescriptions;
        }
        public ActionFilterResult(HttpActionBinding binding, HttpActionContext context, ServicesContainer services,
                                  IActionFilter[] filters)
        {
            Contract.Assert(binding != null);
            Contract.Assert(context != null);
            Contract.Assert(services != null);
            Contract.Assert(filters != null);

            _binding  = binding;
            _context  = context;
            _services = services;
            _filters  = filters;
        }
        /// <summary>
        /// Implementation of <see cref="IActionValueBinder"/>, Primary entry point for binding parameters for an action.
        /// </summary>           
        public virtual HttpActionBinding GetBinding(HttpActionDescriptor actionDescriptor)
        {
            if (actionDescriptor == null)
            {
                throw Error.ArgumentNull("actionDescriptor");
            }

            HttpParameterDescriptor[] parameters = actionDescriptor.GetParameters().ToArray();
            HttpParameterBinding[] binders = Array.ConvertAll(parameters, GetParameterBinding);

            HttpActionBinding actionBinding = new HttpActionBinding(actionDescriptor, binders);

            EnsureOneBodyParameter(actionBinding);

            return actionBinding;
        }
        public HttpActionBindingTracer(HttpActionBinding innerBinding, ITraceWriter traceWriter)
        {
            _innerBinding = innerBinding;
            _traceWriter = traceWriter;

            // Properties that cannot be delegated to the inner must be replicated.
            // They must also avoid an ArgumentNullException for null values.
            if (_innerBinding.ParameterBindings != null)
            {
                ParameterBindings = _innerBinding.ParameterBindings;
            }

            if (_innerBinding.ActionDescriptor != null)
            {
                ActionDescriptor = _innerBinding.ActionDescriptor;
            }
        }
        public HttpActionBindingTracerTest()
        {
            _mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
            _mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            _mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));

            _mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
            _mockParameterBinding = new Mock<HttpParameterBinding>(_mockParameterDescriptor.Object) { CallBase = true };
            _actionBinding = new HttpActionBinding(_mockActionDescriptor.Object, new HttpParameterBinding[] { _mockParameterBinding.Object });

            _controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));

            _controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
            _controllerContext.ControllerDescriptor = _controllerDescriptor;

            _actionContext = ContextUtil.CreateActionContext(_controllerContext, actionDescriptor: _mockActionDescriptor.Object);

        }
        // Creates wrapping tracers for all HttpParameterBindings
        HttpActionBinding IActionValueBinder.GetBinding(HttpActionDescriptor actionDescriptor)
        {
            HttpActionBinding actionBinding = _innerBinder.GetBinding(actionDescriptor);
            HttpParameterBinding[] parameterBindings = actionBinding.ParameterBindings;
            HttpParameterBinding[] newParameterBindings = new HttpParameterBinding[parameterBindings.Length];
            for (int i = 0; i < newParameterBindings.Length; i++)
            {
                HttpParameterBinding parameterBinding = parameterBindings[i];

                // Itercept FormatterParameterBinding to replace its formatters
                FormatterParameterBinding formatterParameterBinding = parameterBinding as FormatterParameterBinding;
                newParameterBindings[i] = formatterParameterBinding != null
                                            ? (HttpParameterBinding)new FormatterParameterBindingTracer(formatterParameterBinding, _traceWriter)
                                            : (HttpParameterBinding)new HttpParameterBindingTracer(parameterBinding, _traceWriter);
            }

            HttpActionBinding newActionBinding = new HttpActionBinding(actionDescriptor, newParameterBindings);
            return newActionBinding;
        }
            public ActionSelectorCacheItem(HttpControllerDescriptor controllerDescriptor)
            {
                Contract.Assert(controllerDescriptor != null);

                // Initialize the cache entirely in the ctor on a single thread.
                _controllerDescriptor = controllerDescriptor;

                MethodInfo[] allMethods   = _controllerDescriptor.ControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
                MethodInfo[] validMethods = Array.FindAll(allMethods, IsValidActionMethod);

                _actionDescriptors = new HttpActionDescriptor[validMethods.Length];
                for (int i = 0; i < validMethods.Length; i++)
                {
                    MethodInfo           method           = validMethods[i];
                    HttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(_controllerDescriptor, method);
                    _actionDescriptors[i] = actionDescriptor;
                    HttpActionBinding actionBinding = controllerDescriptor.ActionValueBinder.GetBinding(actionDescriptor);

                    // Build action parameter name mapping, only consider parameters that are simple types, do not have default values and come from URI
                    _actionParameterNames.Add(
                        actionDescriptor,
                        actionBinding.ParameterBindings
                        .Where(binding => TypeHelper.IsSimpleUnderlyingType(binding.Descriptor.ParameterType) && !binding.HasDefaultValue() && binding.WillReadUri())
                        .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName));
                }

                _actionNameMapping = _actionDescriptors.ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);

                // Bucket the action descriptors by common verbs.
                int len = _cacheListVerbKinds.Length;

                _cacheListVerbs = new ReflectedHttpActionDescriptor[len][];
                for (int i = 0; i < len; i++)
                {
                    _cacheListVerbs[i] = FindActionsForVerbWorker(_cacheListVerbKinds[i]);
                }
            }
            public ActionSelectorCacheItem(HttpControllerDescriptor controllerDescriptor)
            {
                Contract.Assert(controllerDescriptor != null);

                // Initialize the cache entirely in the ctor on a single thread.
                _controllerDescriptor = controllerDescriptor;

                MethodInfo[] allMethods   = _controllerDescriptor.ControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
                MethodInfo[] validMethods = Array.FindAll(allMethods, IsValidActionMethod);

                _combinedCandidateActions = new CandidateAction[validMethods.Length];
                for (int i = 0; i < validMethods.Length; i++)
                {
                    MethodInfo method = validMethods[i];
                    ReflectedHttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(_controllerDescriptor, method);
                    _combinedCandidateActions[i] = new CandidateAction
                    {
                        ActionDescriptor = actionDescriptor
                    };
                    HttpActionBinding actionBinding = actionDescriptor.ActionBinding;

                    // Building an action parameter name mapping to compare against the URI parameters coming from the request. Here we only take into account required parameters that are simple types and come from URI.
                    _actionParameterNames.Add(
                        actionDescriptor,
                        actionBinding.ParameterBindings
                        .Where(binding => !binding.Descriptor.IsOptional && TypeHelper.CanConvertFromString(binding.Descriptor.ParameterType) && binding.WillReadUri())
                        .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName).ToArray());
                }

                if (controllerDescriptor.GetCustomAttributes <IHttpRouteInfoProvider>(inherit: false).Any())
                {
                    // The controller has an attribute route; no actions are accessible via standard routing.
                    _standardCandidateActions = new CandidateAction[0];
                }
                else
                {
                    // The controller does not have an attribute route; some actions may be accessible via standard
                    // routing.
                    List <CandidateAction> standardCandidateActions = new List <CandidateAction>();

                    for (int i = 0; i < _combinedCandidateActions.Length; i++)
                    {
                        CandidateAction candidate = _combinedCandidateActions[i];
                        // Allow standard routes access inherited actions or actions without Route attributes.
                        if (candidate.ActionDescriptor.MethodInfo.DeclaringType != controllerDescriptor.ControllerType ||
                            !candidate.ActionDescriptor.GetCustomAttributes <IHttpRouteInfoProvider>(inherit: false).Any())
                        {
                            standardCandidateActions.Add(candidate);
                        }
                    }

                    _standardCandidateActions = standardCandidateActions.ToArray();
                }

                _combinedActionNameMapping = _combinedCandidateActions.Select(c => c.ActionDescriptor).ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);
                _standardActionNameMapping = _standardCandidateActions.Select(c => c.ActionDescriptor).ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);

                // Bucket the action descriptors by common verbs.
                int len = _cacheListVerbKinds.Length;

                _cacheListVerbs = new CandidateAction[len][];
                for (int i = 0; i < len; i++)
                {
                    _cacheListVerbs[i] = FindActionsForVerbWorker(_cacheListVerbKinds[i]);
                }
            }
 public HttpActionBindingTracer(HttpActionBinding innerBinding, ITraceWriter traceWriter)
 {
     _innerBinding = innerBinding;
     _traceWriter = traceWriter;
 }
        public void GetBinding_DoesNotWrapHttpActionBindingTracer()
        {
            // Arrange
            Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
            Mock<HttpParameterDescriptor> mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
            Mock<FormatterParameterBinding> mockParameterBinding = new Mock<FormatterParameterBinding>(mockParameterDescriptor.Object, new MediaTypeFormatterCollection(), null) { CallBase = true };
            HttpActionBinding actionBinding = new HttpActionBinding(mockActionDescriptor.Object, new HttpParameterBinding[] { mockParameterBinding.Object });

            ITraceWriter traceWriter = new TestTraceWriter();
            HttpActionBindingTracer actionBindingTracer = new HttpActionBindingTracer(actionBinding, traceWriter);
            Mock<IActionValueBinder> mockBinder = new Mock<IActionValueBinder>() { CallBase = true };
            mockBinder.Setup(b => b.GetBinding(It.IsAny<HttpActionDescriptor>())).Returns(actionBindingTracer);
            ActionValueBinderTracer tracer = new ActionValueBinderTracer(mockBinder.Object, traceWriter);

            // Act
            HttpActionBinding actualBinding = ((IActionValueBinder)tracer).GetBinding(mockActionDescriptor.Object);

            // Assert
            Assert.Same(actionBindingTracer, actualBinding);
        }
        public void Decorator_GetInner_On_HttpActionBindingTracer_Returns_HttpActionBinding()
        {
            // Arrange
            HttpActionBinding expectedInner = new HttpActionBinding();
            HttpActionBindingTracer productUnderTest = new HttpActionBindingTracer(expectedInner, new TestTraceWriter());

            // Act
            HttpActionBinding actualInner = Decorator.GetInner(productUnderTest as HttpActionBinding);

            // Assert
            Assert.Same(expectedInner, actualInner);
        }
        public void Inner_Property_On_HttpActionBindingTracer_Returns_HttpActionBinding()
        {
            // Arrange
            HttpActionBinding expectedInner = new HttpActionBinding();
            HttpActionBindingTracer productUnderTest = new HttpActionBindingTracer(expectedInner, new TestTraceWriter());

            // Act
            HttpActionBinding actualInner = productUnderTest.Inner;

            // Assert
            Assert.Same(expectedInner, actualInner);
        }