/// <summary> /// Tries to create a type name segment if the given identifier refers to a known type. /// </summary> /// <param name="previous">previous segment info.</param> /// <param name="segment">The segment being interpreted.</param> /// <param name="typeNameSegment">The type name segment, if one was created.</param> /// <returns>Whether or not a type segment was created for the identifier.</returns> private bool TryCreateTypeNameSegment(SegmentInfo previous, ODataPathSegment segment, out SegmentInfo typeNameSegment) { var typeSegment = segment as TypeSegment; if (typeSegment == null || previous.TargetResourceSet == null) { typeNameSegment = null; return(false); } ResourceType targetResourceType = MetadataProviderUtils.GetResourceType(typeSegment); // if the new type segment prevents any results from possibly being returned, then short-circuit and throw a 404. ResourceType previousResourceType = previous.TargetResourceType; Debug.Assert(previousResourceType != null, "previous.TargetResourceType != null"); if (!targetResourceType.IsAssignableFrom(previousResourceType) && !previousResourceType.IsAssignableFrom(targetResourceType)) { throw DataServiceException.CreateBadRequestError(Strings.RequestUriProcessor_InvalidTypeIdentifier_UnrelatedType(targetResourceType.FullName, previousResourceType.FullName)); } // Since we allow derived navigation properties or named streams in V1/V2, the server will generate edit links and navigation links with type segment in it. // Hence we need to be able to process type segment in the request even when the server MPV is set to V1/V2. But we do not want to expose new functionality // like filtering collections based on type, etc on V1/V2 servers. Hence only checking for MPV to be v3 or greater if the previous segment is a collection if (!previous.SingleResult) { VersionUtil.CheckMaxProtocolVersion(VersionUtil.Version4Dot0, this.maxProtocolVersion); } typeNameSegment = new SegmentInfo { Identifier = targetResourceType.FullName, Operation = previous.Operation, TargetKind = previous.TargetKind, TargetSource = previous.TargetSource, TargetResourceType = targetResourceType, SingleResult = previous.SingleResult, TargetResourceSet = previous.TargetResourceSet, ProjectedProperty = previous.ProjectedProperty, Key = previous.Key, RequestExpression = previous.RequestExpression, RequestEnumerable = previous.RequestEnumerable, IsTypeIdentifierSegment = true }; return(true); }
/// <summary> /// Load operation imports from model's metadata provider. /// </summary> /// <param name="qualifiedName">The name of the entity set to be loaded.</param> /// <returns>Operation imports that are loaded.</returns> internal List <IEdmOperationImport> LazyLoadServiceOperationImports(string qualifiedName) { List <IEdmOperationImport> operationImports = new List <IEdmOperationImport>(); OperationWrapper operationWrapper = this.model.MetadataProvider.TryResolveServiceOperation(qualifiedName); if (operationWrapper != null) { IEdmOperationImport foundOperationImport = this.model.EnsureDefaultEntityContainer().EnsureOperationImport(operationWrapper); if (foundOperationImport != null) { operationImports.Add(foundOperationImport); } } else { var operationWrapperQaulified = this.model.MetadataProvider.TryResolveServiceOperation(this.containerName + "." + qualifiedName); if (operationWrapperQaulified != null) { IEdmOperationImport foundOperationImport = this.model.EnsureDefaultEntityContainer().EnsureOperationImport(operationWrapperQaulified); if (foundOperationImport != null) { operationImports.Add(foundOperationImport); } } } // metadata interface in addition to the action provider interface. if (this.model.ActionProviderWrapper != null) { bool nameIsContainerQualified; var operationName = this.model.MetadataProvider.GetNameFromContainerQualifiedName(qualifiedName, out nameIsContainerQualified); var operation = this.model.ActionProviderWrapper.TryResolveServiceAction(operationName, MetadataProviderUtils.GetResourceType((IEdmType)null)); if (operation != null) { // Only top level actions will have an operation import. IEdmOperationImport foundOperationImport = this.model.EnsureDefaultEntityContainer().EnsureOperationImport(operation); if (foundOperationImport != null) { operationImports.Add(foundOperationImport); } } } return(operationImports); }