예제 #1
0
        public bool Accept(ActionConstraintContext context)
        {
            var queryString = context.RouteContext.HttpContext.Request.QueryString.ToUriComponent();

            var queryStringComponent = queryString.StartsWith("?", StringComparison.Ordinal) ? queryString.Substring(1) : queryString;
            var queryData            = new QueryStringParameterCollection(queryStringComponent);

            var exactCandidates   = context.Candidates.Where(c => c.Action.Parameters.Count == queryData.Count);
            var selectedCandidate = SelectExactCandidate(exactCandidates, queryData);

            if (context.CurrentCandidate.Action == selectedCandidate?.Action)
            {
                return(true);
            }

            var overloadedCandidates = context.Candidates.Where(c => c.Action.Parameters.Count > queryData.Count)
                                       .OrderByDescending(c => c.Action.Parameters.Count);

            selectedCandidate = SelectOverloadedCandidate(overloadedCandidates, queryData);
            if (context.CurrentCandidate.Action == selectedCandidate?.Action)
            {
                return(true);
            }

            return(false);
        }
예제 #2
0
        private ActionSelectorCandidate SelectOverloadedCandidate(IEnumerable <ActionSelectorCandidate> candidates, QueryStringParameterCollection queryData)
        {
            foreach (var candidate in candidates)
            {
                var action = candidate.Action;

                var isMatch    = true;
                var exactCount = 0;
                foreach (var actionParam in action.Parameters)
                {
                    var nameProvider = actionParam.BindingInfo as IModelNameProvider;
                    var name         = nameProvider?.Name ?? actionParam.Name;

                    if (queryData.ContainsKey(name))
                    {
                        if (HasFromQueryAttribute(actionParam))
                        {
                            if (queryData[name].Count() > 1 && !IsCollection(actionParam.ParameterType))
                            {
                                isMatch = false;
                                break;
                            }

                            exactCount++;
                        }
                        else
                        {
                            // parameter with the right name but without FromQueryAttribute
                            isMatch = false;
                            break;
                        }
                    }
                    else
                    {
                        if (HasFromQueryAttribute(actionParam))
                        {
                            // parameter was expected in the query string
                            isMatch = false;
                            break;
                        }
                    }
                }

                if (isMatch && exactCount == queryData.Count)
                {
                    return(candidate);
                }
            }

            return(null);
        }
예제 #3
0
        private ActionSelectorCandidate SelectExactCandidate(IEnumerable <ActionSelectorCandidate> candidates, QueryStringParameterCollection queryData)
        {
            foreach (var candidate in candidates)
            {
                var action = candidate.Action;

                var isMatch = true;
                foreach (var actionParam in action.Parameters)
                {
                    var nameProvider = actionParam.BindingInfo as IModelNameProvider;
                    var name         = nameProvider?.Name ?? actionParam.Name;

                    if (queryData.ContainsKey(name))
                    {
                        isMatch = HasFromQueryAttribute(actionParam);
                        if (!isMatch)
                        {
                            break;
                        }

                        if (queryData[name].Count() > 1 && !IsCollection(actionParam.ParameterType))
                        {
                            isMatch = false;
                            break;
                        }
                    }
                    else
                    {
                        isMatch = false;
                        break;
                    }
                }

                if (isMatch)
                {
                    return(candidate);
                }
            }

            return(null);
        }