public void EndpointConstraint_Accept_ForNoRequestType_ReturnsTrueForAllConstraints(string contentType) { // Arrange var constraint1 = new ConsumesAttribute("application/json"); var endpointWithConstraint = CreateEndpoint(constraint1); var constraint2 = new ConsumesAttribute("text/xml"); var endpointWithConstraint2 = CreateEndpoint(constraint2); var endpointWithoutConstraint = CreateEndpoint(); var context = new EndpointConstraintContext(); context.Candidates = new List <EndpointSelectorCandidate>() { new EndpointSelectorCandidate(endpointWithConstraint, new [] { constraint1 }), new EndpointSelectorCandidate(endpointWithConstraint2, new [] { constraint2 }), }; context.HttpContext = CreateHttpContext(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 EndpointConstraint_Accept_UnrecognizedMediaType_SelectsTheCandidateWithoutConstraintIfPresent(string contentType) { // Arrange var endpointWithoutConstraint = CreateEndpoint(); var constraint1 = new ConsumesAttribute("application/json"); var endpointWithConstraint = CreateEndpoint(constraint1); var constraint2 = new ConsumesAttribute("text/xml"); var endpointWithConstraint2 = CreateEndpoint(constraint2); var context = new EndpointConstraintContext(); context.Candidates = new List <EndpointSelectorCandidate>() { new EndpointSelectorCandidate(endpointWithConstraint, new [] { constraint1 }), new EndpointSelectorCandidate(endpointWithConstraint2, new [] { constraint2 }), new EndpointSelectorCandidate(endpointWithoutConstraint, new List <IEndpointConstraint>()), }; context.HttpContext = CreateHttpContext(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 EndpointConstraint_Accept_ForNoMatchingCandidates_SelectsTheFirstCandidate(string contentType) { // Arrange var constraint1 = new ConsumesAttribute("application/json", "text/xml"); var endpoint1 = CreateEndpoint(constraint1); var constraint2 = new Mock <ITestEndpointConsumeConstraint>(); var endpoint2 = CreateEndpoint(constraint2.Object); constraint2.Setup(o => o.Accept(It.IsAny <EndpointConstraintContext>())) .Returns(false); var context = new EndpointConstraintContext(); context.Candidates = new List <EndpointSelectorCandidate>() { new EndpointSelectorCandidate(endpoint1, new [] { constraint1 }), new EndpointSelectorCandidate(endpoint2, new [] { constraint2.Object }), }; context.CurrentCandidate = context.Candidates[0]; context.HttpContext = CreateHttpContext(contentType: contentType); // Act & Assert Assert.True(constraint1.Accept(context)); }
private static EndpointConstraintContext CreateEndpointConstraintContext(HttpMethodEndpointConstraint constraint) { var context = new EndpointConstraintContext(); var endpointSelectorCandidate = new EndpointSelectorCandidate(new TestEndpoint(EndpointMetadataCollection.Empty, string.Empty), new List <IEndpointConstraint> { constraint }); context.Candidates = new List <EndpointSelectorCandidate> { endpointSelectorCandidate }; context.CurrentCandidate = context.Candidates[0]; return(context); }
public void EndpointConstraint_Accept_MatchesForMachingRequestContentType(string contentType) { // Arrange var constraint = new ConsumesAttribute("application/json", "text/xml"); var endpoint = CreateEndpoint(constraint); var context = new EndpointConstraintContext(); context.Candidates = new List <EndpointSelectorCandidate>() { new EndpointSelectorCandidate(endpoint, new [] { constraint }), }; context.CurrentCandidate = context.Candidates[0]; context.HttpContext = CreateHttpContext(contentType: contentType); // Act & Assert Assert.True(constraint.Accept(context)); }
/// <inheritdoc /> public bool Accept(EndpointConstraintContext context) { // If this constraint is not closest to the endpoint, it will be skipped. if (!IsApplicable(context.CurrentCandidate.Endpoint)) { // 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 endpoint. return(true); } var requestContentType = context.HttpContext.Request.ContentType; // 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 endpoints with consumes endpoint constraints this should result in ambiguous exception // unless there is another endpoint without a consumes constraint. if (requestContentType == null) { var isEndpointWithoutConsumeConstraintPresent = context.Candidates.Any( candidate => candidate.Constraints == null || !candidate.Constraints.Any(constraint => constraint is IConsumesEndpointConstraint)); return(!isEndpointWithoutConsumeConstraintPresent); } // Confirm the request's content type is more specific than (a media type this endpoint supports e.g. OK // if client sent "text/plain" data and this endpoint supports "text/*". if (IsSubsetOfAnyContentType(requestContentType)) { return(true); } var firstCandidate = context.Candidates[0]; if (firstCandidate.Endpoint != context.CurrentCandidate.Endpoint) { // 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 IConsumesEndpointConstraints 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.Endpoint == firstCandidate.Endpoint) { continue; } var tempContext = new EndpointConstraintContext() { Candidates = context.Candidates, HttpContext = context.HttpContext, CurrentCandidate = candidate }; if (candidate.Constraints == null || candidate.Constraints.Count == 0 || candidate.Constraints.Any(constraint => constraint is IConsumesEndpointConstraint && 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); }
public bool Accept(EndpointConstraintContext context) { return(ProcessRequest(context.HttpContext.Request)); }
bool IEndpointConstraint.Accept(EndpointConstraintContext context) { return(AcceptCore()); }