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 void Accept_ForNoRequestType_ReturnsTrueForAllConstraints(string contentType) { // Arrange var constraint1 = new ConsumesAttribute("application/json"); var actionWithConstraint = new ActionDescriptor() { FilterDescriptors = new List <FilterDescriptor>() { new FilterDescriptor(constraint1, FilterScope.Action) } }; var constraint2 = new ConsumesAttribute("text/xml"); var actionWithConstraint2 = new ActionDescriptor() { FilterDescriptors = new List <FilterDescriptor>() { new FilterDescriptor(constraint2, FilterScope.Action) } }; var actionWithoutConstraint = new ActionDescriptor(); var context = new ActionConstraintContext(); context.Candidates = new List <ActionSelectorCandidate>() { new ActionSelectorCandidate(actionWithConstraint, new [] { constraint1 }), new ActionSelectorCandidate(actionWithConstraint2, new [] { constraint2 }), }; context.RouteContext = CreateRouteContext(contentType: contentType); // Act & Assert context.CurrentCandidate = context.Candidates[0]; Assert.True(constraint1.Accept(context)); context.CurrentCandidate = context.Candidates[1]; Assert.True(constraint2.Accept(context)); }
public void Accept_ForNoMatchingCandidates_SelectsTheFirstCandidate(string contentType) { // Arrange var constraint1 = new ConsumesAttribute("application/json", "text/xml"); var action1 = new ActionDescriptor() { FilterDescriptors = new List <FilterDescriptor>() { new FilterDescriptor(constraint1, FilterScope.Action) } }; var constraint2 = new Mock <ITestConsumeConstraint>(); var action2 = new ActionDescriptor() { FilterDescriptors = new List <FilterDescriptor>() { new FilterDescriptor(constraint2.Object, FilterScope.Action) } }; constraint2.Setup(o => o.Accept(It.IsAny <ActionConstraintContext>())) .Returns(false); var context = new ActionConstraintContext(); context.Candidates = new List <ActionSelectorCandidate>() { new ActionSelectorCandidate(action1, new [] { constraint1 }), new ActionSelectorCandidate(action2, new [] { constraint2.Object }), }; context.CurrentCandidate = context.Candidates[0]; context.RouteContext = CreateRouteContext(contentType: contentType); // Act & Assert Assert.True(constraint1.Accept(context)); }
public void Accept_MatchesForMachingRequestContentType(string contentType) { // Arrange var constraint = new ConsumesAttribute("application/json", "text/xml"); var action = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint, FilterScope.Action) } }; var context = new ActionConstraintContext(); context.Candidates = new List<ActionSelectorCandidate>() { new ActionSelectorCandidate(action, new [] { constraint }), }; context.CurrentCandidate = context.Candidates[0]; context.RouteContext = CreateRouteContext(contentType: contentType); // Act & Assert Assert.True(constraint.Accept(context)); }
public bool Accept([NotNull] ActionConstraintContext context) { return(Pass); }
public bool Accept(ActionConstraintContext context) { // If this constraint is not closest to the action, it will be skipped. if (!IsApplicable(context.CurrentCandidate.Action)) { // Since the constraint is to be skipped, returning true here // will let the current candidate ignore this constraint and will // be selected based on other constraints for this action. return(true); } MediaTypeHeaderValue requestContentType = null; MediaTypeHeaderValue.TryParse(context.RouteContext.HttpContext.Request.ContentType, out requestContentType); // If the request content type is null we need to act like pass through. // In case there is a single candidate with a constraint it should be selected. // If there are multiple actions with consumes action constraints this should result in ambiguous exception // unless there is another action without a consumes constraint. if (requestContentType == null) { var isActionWithoutConsumeConstraintPresent = context.Candidates.Any( candidate => candidate.Constraints == null || !candidate.Constraints.Any(constraint => constraint is IConsumesActionConstraint)); return(!isActionWithoutConsumeConstraintPresent); } if (ContentTypes.Any(c => c.IsSubsetOf(requestContentType))) { return(true); } var firstCandidate = context.Candidates[0]; if (firstCandidate != context.CurrentCandidate) { // If the current candidate is not same as the first candidate, // we need not probe other candidates to see if they apply. // Only the first candidate is allowed to probe other candidates and based on the result select itself. return(false); } // Run the matching logic for all IConsumesActionConstraints we can find, and see what matches. // 1). If we have a unique best match, then only that constraint should return true. // 2). If we have multiple matches, then all constraints that match will return true // , resulting in ambiguity(maybe). // 3). If we have no matches, then we choose the first constraint to return true.It will later return a 415 foreach (var candidate in context.Candidates) { if (candidate == firstCandidate) { continue; } var tempContext = new ActionConstraintContext() { Candidates = context.Candidates, RouteContext = context.RouteContext, CurrentCandidate = candidate }; if (candidate.Constraints == null || candidate.Constraints.Count == 0 || candidate.Constraints.Any(constraint => constraint is IConsumesActionConstraint && constraint.Accept(tempContext))) { // There is someone later in the chain which can handle the request. // end the process here. return(false); } } // There is no one later in the chain that can handle this content type return a false positive so that // later we can detect and return a 415. return(true); }
/// <inheritdoc /> public bool Accept(ActionConstraintContext context) { return(IsValidForRequest(context.RouteContext, context.CurrentCandidate.Action)); }
public bool Accept(ActionConstraintContext context) { // If this constraint is not closest to the action, it will be skipped. if (!IsApplicable(context.CurrentCandidate.Action)) { // Since the constraint is to be skipped, returning true here // will let the current candidate ignore this constraint and will // be selected based on other constraints for this action. return true; } MediaTypeHeaderValue requestContentType = null; MediaTypeHeaderValue.TryParse(context.RouteContext.HttpContext.Request.ContentType, out requestContentType); // If the request content type is null we need to act like pass through. // In case there is a single candidate with a constraint it should be selected. // If there are multiple actions with consumes action constraints this should result in ambiguous exception // unless there is another action without a consumes constraint. if (requestContentType == null) { var isActionWithoutConsumeConstraintPresent = context.Candidates.Any( candidate => candidate.Constraints == null || !candidate.Constraints.Any(constraint => constraint is IConsumesActionConstraint)); return !isActionWithoutConsumeConstraintPresent; } if (ContentTypes.Any(c => c.IsSubsetOf(requestContentType))) { return true; } var firstCandidate = context.Candidates[0]; if (firstCandidate != context.CurrentCandidate) { // If the current candidate is not same as the first candidate, // we need not probe other candidates to see if they apply. // Only the first candidate is allowed to probe other candidates and based on the result select itself. return false; } // Run the matching logic for all IConsumesActionConstraints we can find, and see what matches. // 1). If we have a unique best match, then only that constraint should return true. // 2). If we have multiple matches, then all constraints that match will return true // , resulting in ambiguity(maybe). // 3). If we have no matches, then we choose the first constraint to return true.It will later return a 415 foreach (var candidate in context.Candidates) { if (candidate == firstCandidate) { continue; } var tempContext = new ActionConstraintContext() { Candidates = context.Candidates, RouteContext = context.RouteContext, CurrentCandidate = candidate }; if (candidate.Constraints == null || candidate.Constraints.Count == 0 || candidate.Constraints.Any(constraint => constraint is IConsumesActionConstraint && constraint.Accept(tempContext))) { // There is someone later in the chain which can handle the request. // end the process here. return false; } } // There is no one later in the chain that can handle this content type return a false positive so that // later we can detect and return a 415. return true; }
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)); } }
/// <inheritdoc /> public bool Accept(ActionConstraintContext context) { return IsValidForRequest(context.RouteContext, context.CurrentCandidate.Action); }
public void Accept_ForNoRequestType_ReturnsTrueForAllConstraints(string contentType) { // Arrange var constraint1 = new ConsumesAttribute("application/json"); var actionWithConstraint = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint1, FilterScope.Action) } }; var constraint2 = new ConsumesAttribute("text/xml"); var actionWithConstraint2 = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint2, FilterScope.Action) } }; var actionWithoutConstraint = new ActionDescriptor(); var context = new ActionConstraintContext(); context.Candidates = new List<ActionSelectorCandidate>() { new ActionSelectorCandidate(actionWithConstraint, new [] { constraint1 }), new ActionSelectorCandidate(actionWithConstraint2, new [] { constraint2 }), }; context.RouteContext = CreateRouteContext(contentType: contentType); // Act & Assert context.CurrentCandidate = context.Candidates[0]; Assert.True(constraint1.Accept(context)); context.CurrentCandidate = context.Candidates[1]; Assert.True(constraint2.Accept(context)); }
public void Accept_UnrecognizedMediaType_SelectsTheCandidateWithoutConstraintIfPresent(string contentType) { // Arrange var actionWithoutConstraint = new ActionDescriptor(); var constraint1 = new ConsumesAttribute("application/json"); var actionWithConstraint = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint1, FilterScope.Action) } }; var constraint2 = new ConsumesAttribute("text/xml"); var actionWithConstraint2 = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint2, FilterScope.Action) } }; var context = new ActionConstraintContext(); context.Candidates = new List<ActionSelectorCandidate>() { new ActionSelectorCandidate(actionWithConstraint, new [] { constraint1 }), new ActionSelectorCandidate(actionWithConstraint2, new [] { constraint2 }), new ActionSelectorCandidate(actionWithoutConstraint, new List<IActionConstraint>()), }; context.RouteContext = CreateRouteContext(contentType: contentType); // Act & Assert context.CurrentCandidate = context.Candidates[0]; Assert.False(constraint1.Accept(context)); context.CurrentCandidate = context.Candidates[1]; Assert.False(constraint2.Accept(context)); }
public void Accept_ForNoMatchingCandidates_SelectsTheFirstCandidate(string contentType) { // Arrange var constraint1 = new ConsumesAttribute("application/json", "text/xml"); var action1 = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint1, FilterScope.Action) } }; var constraint2 = new Mock<ITestConsumeConstraint>(); var action2 = new ActionDescriptor() { FilterDescriptors = new List<FilterDescriptor>() { new FilterDescriptor(constraint2.Object, FilterScope.Action) } }; constraint2.Setup(o => o.Accept(It.IsAny<ActionConstraintContext>())) .Returns(false); var context = new ActionConstraintContext(); context.Candidates = new List<ActionSelectorCandidate>() { new ActionSelectorCandidate(action1, new [] { constraint1 }), new ActionSelectorCandidate(action2, new [] { constraint2.Object }), }; context.CurrentCandidate = context.Candidates[0]; context.RouteContext = CreateRouteContext(contentType: contentType); // Act & Assert Assert.True(constraint1.Accept(context)); }