public void Accept_RejectsActionMatchWithMissingParameter()
        {
            // Arrange
            var action = new ActionDescriptor();
            action.Parameters = new List<ParameterDescriptor>()
            {
                new ParameterDescriptor()
                {
                    BindingInfo = new BindingInfo()
                    {
                      BindingSource = (new FromUriAttribute()).BindingSource,
                    },
                    Name = "id",
                    ParameterType = typeof(int),
                },
            };

            var constraint = new OverloadActionConstraint();

            var context = new ActionConstraintContext();
            context.Candidates = new List<ActionSelectorCandidate>()
            {
                new ActionSelectorCandidate(action, new [] { constraint }),
            };

            context.CurrentCandidate = context.Candidates[0];
            context.RouteContext = CreateRouteContext();

            // Act & Assert
            Assert.False(constraint.Accept(context));
        }
 public bool Accept(ActionConstraintContext context)
 {
     return string.Equals(
         context.RouteContext.RouteData.Values["country"].ToString(),
         _countryCode,
         StringComparison.OrdinalIgnoreCase);
 }
 public bool Accept(ActionConstraintContext context)
 {
     int version;
     if (int.TryParse(GetVersion(context.RouteContext.HttpContext.Request), out version))
     {
         return (_minVersion == null || _minVersion <= version) &&
             (_maxVersion == null || _maxVersion >= version);
     }
     else
     {
         return false;
     }
 }
        public bool Accept(ActionConstraintContext context)
        {
            var candidates = context.Candidates.Select(c => new
            {
                Action = c,
                Parameters = GetOverloadableParameters(c),
            });

            // Combined route value keys and query string keys. These are the values available for overload selection.
            var requestKeys = GetCombinedKeys(context.RouteContext);

            // Group candidates by the highest number of keys, and then process them until we find an action
            // with all parameters satisfied.
            foreach (var group in candidates.GroupBy(c => c.Parameters?.Count ?? 0).OrderByDescending(g => g.Key))
            {
                var foundMatch = false;
                foreach (var candidate in group)
                {
                    var allFound = true;
                    if (candidate.Parameters != null)
                    {
                        foreach (var parameter in candidate.Parameters)
                        {
                            if (!requestKeys.Contains(parameter.Prefix))
                            {
                                if (candidate.Action.Action == context.CurrentCandidate.Action)
                                {
                                    return false;
                                }

                                allFound = false;
                                break;
                            }
                        }
                    }

                    if (allFound)
                    {
                        foundMatch = true;
                    }
                }

                if (foundMatch)
                {
                    return group.Any(c => c.Action.Action == context.CurrentCandidate.Action);
                }
            }

            return false;
        }
        public bool Accept(ActionConstraintContext context)
        {
            //Initialize the context, this will be called a few times but the initialize logic
            // only executes once. There might be a nicer way to do this but the RouteContext and
            // other request scoped instances are not available yet.
            _umbCtx.Initialize(context.RouteContext.RouteData);

            if (_umbCtx.HasContent == false) return false;

            //NOTE: This was for testing at some point!

            //if (((ControllerActionDescriptor)context.CurrentCandidate.Action)
            //    .ControllerName == "TestSurface")
            //{
            //    return true;
            //}

            return false;
        }
        public void Accept_AcceptsActionWithSatisfiedParameters()
        {
            // Arrange
            var action = new ActionDescriptor();
            action.Parameters = new List<ParameterDescriptor>()
            {
                new ParameterDescriptor()
                {
                    BindingInfo = new BindingInfo()
                    {
                      BindingSource = (new FromUriAttribute()).BindingSource,
                    },
                    Name = "id",
                    ParameterType = typeof(int),
                },
                new ParameterDescriptor()
                {
                    BindingInfo = new BindingInfo()
                    {
                      BindingSource = (new FromUriAttribute()).BindingSource,
                    },
                    Name = "quantity",
                    ParameterType = typeof(int),
                },
            };

            var constraint = new OverloadActionConstraint();

            var context = new ActionConstraintContext();
            context.Candidates = new List<ActionSelectorCandidate>()
            {
                new ActionSelectorCandidate(action, new [] { constraint }),
            };

            context.CurrentCandidate = context.Candidates[0];
            context.RouteContext = CreateRouteContext("?quantity=5", new { id = 17 });

            // Act & Assert
            Assert.True(constraint.Accept(context));
        }
Beispiel #7
0
        public bool Accept(ActionConstraintContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (_httpMethods.Count == 0)
            {
                return(true);
            }

            var request = context.RouteContext.HttpContext.Request;
            var method  = request.Method;

            if (request.Headers.ContainsKey(OriginHeader))
            {
                // Update the http method if it is preflight request.
                var accessControlRequestMethod = request.Headers[AccessControlRequestMethod];
                if (string.Equals(
                        request.Method,
                        PreflightHttpMethod,
                        StringComparison.Ordinal) &&
                    !StringValues.IsNullOrEmpty(accessControlRequestMethod))
                {
                    method = accessControlRequestMethod;
                }
            }

            for (var i = 0; i < _httpMethods.Count; i++)
            {
                var supportedMethod = _httpMethods[i];
                if (string.Equals(supportedMethod, method, StringComparison.Ordinal))
                {
                    return(true);
                }
            }

            return(false);
        }
        public bool Accept(ActionConstraintContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (_httpMethods.Count == 0)
            {
                return true;
            }

            var request = context.RouteContext.HttpContext.Request;
            var method = request.Method;
            if (request.Headers.ContainsKey(OriginHeader))
            {
                // Update the http method if it is preflight request.
                var accessControlRequestMethod = request.Headers[AccessControlRequestMethod];
                if (string.Equals(
                        request.Method,
                        PreflightHttpMethod,
                        StringComparison.OrdinalIgnoreCase) &&
                    !StringValues.IsNullOrEmpty(accessControlRequestMethod))
                {
                    method = accessControlRequestMethod;
                }
            }

            for (var i = 0; i < _httpMethods.Count; i++)
            {
                var supportedMethod = _httpMethods[i];
                if (string.Equals(supportedMethod, method, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }

            return false;
        }
        private IReadOnlyList<ActionSelectorCandidate> EvaluateActionConstraints(
            RouteContext context,
            IReadOnlyList<ActionSelectorCandidate> candidates,
            int? startingOrder)
        {
            // Find the next group of constraints to process. This will be the lowest value of
            // order that is higher than startingOrder.
            int? order = null;

            // Perf: Avoid allocations
            for (var i = 0; i < candidates.Count; i++)
            {
                var candidate = candidates[i];
                if (candidate.Constraints != null)
                {
                    for (var j = 0; j < candidate.Constraints.Count; j++)
                    {
                        var constraint = candidate.Constraints[j];
                        if ((startingOrder == null || constraint.Order > startingOrder) &&
                            (order == null || constraint.Order < order))
                        {
                            order = constraint.Order;
                        }
                    }
                }
            }

            // If we don't find a 'next' then there's nothing left to do.
            if (order == null)
            {
                return candidates;
            }

            // Since we have a constraint to process, bisect the set of actions into those with and without a
            // constraint for the 'current order'.
            var actionsWithConstraint = new List<ActionSelectorCandidate>();
            var actionsWithoutConstraint = new List<ActionSelectorCandidate>();

            var constraintContext = new ActionConstraintContext();
            constraintContext.Candidates = candidates;
            constraintContext.RouteContext = context;

            // Perf: Avoid allocations
            for (var i = 0; i < candidates.Count; i++)
            {
                var candidate = candidates[i];
                var isMatch = true;
                var foundMatchingConstraint = false;

                if (candidate.Constraints != null)
                {
                    constraintContext.CurrentCandidate = candidate;
                    for (var j = 0; j < candidate.Constraints.Count; j++)
                    {
                        var constraint = candidate.Constraints[j];
                        if (constraint.Order == order)
                        {
                            foundMatchingConstraint = true;

                            if (!constraint.Accept(constraintContext))
                            {
                                isMatch = false;

                                _logger.LogVerbose(
                                    "Action '{ActionDisplayName}' with id '{ActionId}' did not match the " +
                                    "constraint '{ActionConstraint}'",
                                    candidate.Action.DisplayName,
                                    candidate.Action.Id,
                                    constraint);

                                break;
                            }
                        }
                    }
                }

                if (isMatch && foundMatchingConstraint)
                {
                    actionsWithConstraint.Add(candidate);
                }
                else if (isMatch)
                {
                    actionsWithoutConstraint.Add(candidate);
                }
            }

            // If we have matches with constraints, those are 'better' so try to keep processing those
            if (actionsWithConstraint.Count > 0)
            {
                var matches = EvaluateActionConstraints(context, actionsWithConstraint, order);
                if (matches?.Count > 0)
                {
                    return matches;
                }
            }

            // If the set of matches with constraints can't work, then process the set without constraints.
            if (actionsWithoutConstraint.Count == 0)
            {
                return null;
            }
            else
            {
                return EvaluateActionConstraints(context, actionsWithoutConstraint, order);
            }
        }
 public bool Accept(ActionConstraintContext context)
 {
     return Pass;
 }
        private IReadOnlyList<ActionSelectorCandidate> EvaluateActionConstraints(
            RouteContext context,
            IReadOnlyList<ActionSelectorCandidate> candidates,
            int? startingOrder)
        {
            // Find the next group of constraints to process. This will be the lowest value of
            // order that is higher than startingOrder.
            int? order = null;
            foreach (var candidate in candidates)
            {
                if (candidate.Constraints != null)
                {
                    foreach (var constraint in candidate.Constraints)
                    {
                        if ((startingOrder == null || constraint.Order > startingOrder) &&
                            (order == null || constraint.Order < order))
                        {
                            order = constraint.Order;
                        }
                    }
                }
            }

            // If we don't find a 'next' then there's nothing left to do.
            if (order == null)
            {
                return candidates;
            }

            // Since we have a constraint to process, bisect the set of actions into those with and without a
            // constraint for the 'current order'.
            var actionsWithConstraint = new List<ActionSelectorCandidate>();
            var actionsWithoutConstraint = new List<ActionSelectorCandidate>();

            var constraintContext = new ActionConstraintContext();
            constraintContext.Candidates = candidates;
            constraintContext.RouteContext = context;

            foreach (var candidate in candidates)
            {
                var isMatch = true;
                var foundMatchingConstraint = false;

                if (candidate.Constraints != null)
                {
                    constraintContext.CurrentCandidate = candidate;
                    foreach (var constraint in candidate.Constraints)
                    {
                        if (constraint.Order == order)
                        {
                            foundMatchingConstraint = true;

                            if (!constraint.Accept(constraintContext))
                            {
                                isMatch = false;
                                break;
                            }
                        }
                    }
                }

                if (isMatch && foundMatchingConstraint)
                {
                    actionsWithConstraint.Add(candidate);
                }
                else if (isMatch)
                {
                    actionsWithoutConstraint.Add(candidate);
                }
            }

            // If we have matches with constraints, those are 'better' so try to keep processing those
            if (actionsWithConstraint.Count > 0)
            {
                var matches = EvaluateActionConstraints(context, actionsWithConstraint, order);
                if (matches?.Count > 0)
                {
                    return matches;
                }
            }

            // If the set of matches with constraints can't work, then process the set without constraints.
            if (actionsWithoutConstraint.Count == 0)
            {
                return null;
            }
            else
            {
                return EvaluateActionConstraints(context, actionsWithoutConstraint, order);
            }
        }
        public void Accept_AcceptsAction_WithFewerParameters_WhenOtherIsNotOverloaded()
        {
            // Arrange
            var action1 = new ActionDescriptor();
            action1.Parameters = new List<ParameterDescriptor>()
            {
                new ParameterDescriptor()
                {
                    BindingInfo = new BindingInfo()
                    {
                      BindingSource = (new FromUriAttribute()).BindingSource,
                    },
                    Name = "id",
                    ParameterType = typeof(int),
                },
            };

            var action2 = new ActionDescriptor();
            action2.Parameters = new List<ParameterDescriptor>()
            {
                new ParameterDescriptor()
                {
                    BindingInfo = new BindingInfo()
                    {
                      BindingSource = (new FromUriAttribute()).BindingSource,
                    },
                    Name = "id",
                    ParameterType = typeof(int),
                },
                new ParameterDescriptor()
                {
                    BindingInfo = new BindingInfo()
                    {
                      BindingSource = (new FromUriAttribute()).BindingSource,
                    },
                    Name = "quantity",
                    ParameterType = typeof(int),
                },
            };

            var optionalParameters = new HashSet<string>();
            optionalParameters.Add("quantity");
            action2.Properties.Add("OptionalParameters", optionalParameters);

            var constraint = new OverloadActionConstraint();

            var context = new ActionConstraintContext();
            context.Candidates = new List<ActionSelectorCandidate>()
            {
                new ActionSelectorCandidate(action1, new [] { constraint }),
                new ActionSelectorCandidate(action2, new IActionConstraint[] { }),
            };

            context.CurrentCandidate = context.Candidates[0];
            context.RouteContext = CreateRouteContext("?quantity=5", new { id = 17 });

            // Act & Assert
            Assert.True(constraint.Accept(context));
        }
 public bool Accept(ActionConstraintContext context)
 {
     return false;
 }
 /// <inheritdoc />
 public bool Accept(ActionConstraintContext context)
 {
     return(IsValidForRequest(context.RouteContext, context.CurrentCandidate.Action));
 }
 public bool Accept(ActionConstraintContext context)
 {
     return _requestId == _requestIdService.RequestId;
 }
 /// <inheritdoc />
 public bool Accept(ActionConstraintContext context)
 {
     return IsValidForRequest(context.RouteContext, context.CurrentCandidate.Action);
 }