/// <summary> /// Handle $count segment /// </summary> /// <param name="previous">previous segment info.</param> /// <returns>The count segment info</returns> private static SegmentInfo CreateCountSegment(SegmentInfo previous) { CheckSegmentIsComposable(previous); if ((previous.TargetKind != RequestTargetKind.Resource || previous.SingleResult) && previous.TargetKind != RequestTargetKind.Collection) { throw DataServiceException.CreateResourceNotFound(Strings.RequestUriProcessor_CountNotSupported(previous.Identifier)); } var segment = new SegmentInfo(); segment.Identifier = XmlConstants.UriCountSegment; // DEVNOTE: prior to refactoring, $count was handled alongside properties // TODO: introduce a new target-source value or otherwise refactor this so that // $count is not treated like a property. Using the previous segment's kind // becomes problematic for service operations because the current segment // will not know the specific operation. segment.TargetSource = RequestTargetSource.Property; segment.SingleResult = true; segment.TargetKind = RequestTargetKind.PrimitiveValue; segment.TargetResourceType = previous.TargetResourceType; segment.TargetResourceSet = previous.TargetResourceSet; return(segment); }
/// <summary> /// Creates a property segment /// </summary> /// <param name="previous">previous segment info.</param> /// <param name="property">property to create the segment for.</param> /// <returns>new segment for the given property.</returns> private SegmentInfo CreatePropertySegment(SegmentInfo previous, ResourceProperty property) { // Handle a strongly-typed property. SegmentInfo segment = new SegmentInfo() { Identifier = property.Name, ProjectedProperty = property }; segment.TargetResourceType = property.ResourceType; ResourcePropertyKind propertyKind = property.Kind; segment.SingleResult = (propertyKind != ResourcePropertyKind.ResourceSetReference); segment.TargetSource = RequestTargetSource.Property; if (previous.TargetKind == RequestTargetKind.Link && property.TypeKind != ResourceTypeKind.EntityType) { throw DataServiceException.CreateBadRequestError(Strings.RequestUriProcessor_LinkSegmentMustBeFollowedByEntitySegment(segment.Identifier, XmlConstants.UriLinkSegment)); } switch (propertyKind) { case ResourcePropertyKind.ComplexType: segment.TargetKind = RequestTargetKind.ComplexObject; break; case ResourcePropertyKind.Collection: segment.TargetKind = RequestTargetKind.Collection; break; case ResourcePropertyKind.ResourceReference: case ResourcePropertyKind.ResourceSetReference: segment.TargetKind = RequestTargetKind.Resource; segment.TargetResourceSet = this.providerWrapper.GetResourceSet(previous.TargetResourceSet, previous.TargetResourceType, property); if (segment.TargetResourceSet == null) { throw DataServiceException.CreateResourceNotFound(property.Name); } break; default: Debug.Assert(property.IsOfKind(ResourcePropertyKind.Primitive), "must be primitive type property"); segment.TargetKind = RequestTargetKind.Primitive; break; } return(segment); }
/// <summary>Creates the first <see cref="SegmentInfo"/> for a request.</summary> /// <param name="segment">The text of the segment.</param> /// <returns>A description of the information on the segment.</returns> private SegmentInfo CreateFirstSegment(ODataPathSegment segment) { Debug.Assert(segment != null, "identifier != null"); // Look for well-known system entry points. if (segment is MetadataSegment) { return(new SegmentInfo { Identifier = XmlConstants.UriMetadataSegment, TargetKind = RequestTargetKind.Metadata }); } if (segment is BatchSegment) { return(new SegmentInfo { Identifier = XmlConstants.UriBatchSegment, TargetKind = RequestTargetKind.Batch }); } if (segment is CountSegment) { // $count on root: throw throw DataServiceException.CreateResourceNotFound(Strings.RequestUriProcessor_CountOnRoot); } // Look for a service operation. OperationImportSegment serviceOperation = segment as OperationImportSegment; if (serviceOperation != null) { Debug.Assert(serviceOperation.OperationImports.Count() == 1, "Operation import segment should only ever have exactly one operation. Was a change made to how MetadataProviderEdmModel finds actions/service operations"); var operationImport = serviceOperation.OperationImports.Single(); var operation = ((MetadataProviderEdmOperationImport)operationImport).ServiceOperation; Debug.Assert(operation != null, "operation != null"); if (operation.Kind == OperationKind.ServiceOperation) { return(CreateSegmentForServiceOperation(operation)); } Debug.Assert(operation.Kind == OperationKind.Action, "serviceAction.Kind == OperationKind.Action"); return(this.CreateSegmentForServiceAction(null /*previousSegment*/, operation)); } var batchReferenceSegment = segment as BatchReferenceSegment; if (batchReferenceSegment != null) { SegmentInfo referencedSegmentInfo = this.crossReferenceCallback(batchReferenceSegment.ContentId); Debug.Assert(referencedSegmentInfo != null, "Could not find SegmentInfo for content-id: " + batchReferenceSegment.ContentId); referencedSegmentInfo.Identifier = batchReferenceSegment.ContentId; return(referencedSegmentInfo); } // Look for an entity set. EntitySetSegment entitySetSegment = segment as EntitySetSegment; if (entitySetSegment != null) { var container = ((IResourceSetBasedEdmEntitySet)entitySetSegment.EntitySet).ResourceSet; Debug.Assert(container != null, "container != null"); SegmentInfo segmentInfo = new SegmentInfo { Identifier = container.Name, TargetResourceSet = container, TargetResourceType = container.ResourceType, TargetSource = RequestTargetSource.EntitySet, TargetKind = RequestTargetKind.Resource, SingleResult = false }; return(segmentInfo); } WebUtil.CheckResourceExists(false, segment.ToString()); return(null); }