/// <summary> /// Composes the specified <paramref name="queryExpression"/> for the /// given <paramref name="container"/> with authorization /// callbacks. /// </summary> /// <param name="service">Data service on which to invoke method.</param> /// <param name="container">resource set to compose with.</param> /// <param name="queryExpression">Query to compose.</param> /// <returns>The resulting composed query.</returns> internal static Expression ComposeResourceContainer(IDataService service, ResourceSetWrapper container, Expression queryExpression) { Debug.Assert(service != null, "service != null"); Debug.Assert(container != null, "container != null"); Debug.Assert(queryExpression != null, "queryExpression != null"); MethodInfo[] methods = container.QueryInterceptors; if (methods != null) { for (int i = 0; i < methods.Length; i++) { Expression predicate; try { predicate = (Expression)methods[i].Invoke(service.Instance, WebUtil.EmptyObjectArray); } catch (TargetInvocationException tie) { ErrorHandler.HandleTargetInvocationException(tie); throw; } if (predicate == null) { throw new InvalidOperationException(Strings.DataService_AuthorizationReturnedNullQuery(methods[i].Name, methods[i].DeclaringType.FullName)); } // predicate is LambdaExpression -- otherwise signature check missed something and following cast would throw queryExpression = queryExpression.QueryableWhere((LambdaExpression)predicate); } } return(queryExpression); }
protected void UpdateAndCheckRequestResponseDSV(ResourceType resourceType, bool topLevel) { bool flag = this.ContentFormat == System.Data.Services.ContentFormat.Atom; if (flag) { Version requiredVersion = resourceType.EpmMinimumDataServiceProtocolVersion.ToVersion(); this.RequestDescription.VerifyRequestVersion(requiredVersion, this.service); } if (topLevel && this.ResponseWillBeSent) { Version version2; bool considerEpmInVersion = WebUtil.IsAtomResponseFormat(this.Service.OperationContext.Host.RequestAccept, this.RequestDescription.TargetKind, this.Service.Configuration.DataServiceBehavior.MaxProtocolVersion, this.Service.OperationContext.Host.RequestMaxVersion); ResourceSetWrapper targetContainer = this.RequestDescription.LastSegmentInfo.TargetContainer; if (flag) { version2 = resourceType.GetMinimumResponseVersion(this.Service, targetContainer, considerEpmInVersion); } else { version2 = resourceType.GetMinimumResponseVersion(this.Service, targetContainer, considerEpmInVersion); if (considerEpmInVersion && (version2 <= System.Data.Services.RequestDescription.Version2Dot0)) { this.RequestDescription.VerifyAndRaiseActualResponseVersion(version2, this.service); version2 = resourceType.GetMinimumResponseVersion(this.Service, targetContainer, false); } } this.RequestDescription.VerifyAndRaiseResponseVersion(version2, this.Service); } }
internal static Expression ComposeResourceContainer(IDataService service, ResourceSetWrapper container, Expression queryExpression) { MethodInfo[] queryInterceptors = container.QueryInterceptors; if (queryInterceptors != null) { for (int i = 0; i < queryInterceptors.Length; i++) { Expression expression; try { expression = (Expression)queryInterceptors[i].Invoke(service.Instance, WebUtil.EmptyObjectArray); } catch (TargetInvocationException exception) { ErrorHandler.HandleTargetInvocationException(exception); throw; } if (expression == null) { throw new InvalidOperationException(System.Data.Services.Strings.DataService_AuthorizationReturnedNullQuery(queryInterceptors[i].Name, queryInterceptors[i].DeclaringType.FullName)); } queryExpression = queryExpression.QueryableWhere((LambdaExpression)expression); } } return(queryExpression); }
/// <summary>Fires the notification for a single action.</summary> /// <param name="service">Service on which methods should be invoked.</param> /// <param name="target">Object to be tracked.</param> /// <param name="container">Container in which object is changed.</param> /// <param name="action">Action affecting target.</param> internal static void FireNotification(IDataService service, object target, ResourceSetWrapper container, UpdateOperations action) { Debug.Assert(service != null, "service != null"); AssertActionValues(target, container); MethodInfo[] methods = container.ChangeInterceptors; if (methods != null) { object[] parameters = new object[2]; parameters[0] = target; parameters[1] = action; for (int i = 0; i < methods.Length; i++) { try { methods[i].Invoke(service.Instance, parameters); } catch (TargetInvocationException exception) { ErrorHandler.HandleTargetInvocationException(exception); throw; } } } }
internal void TrackAction(object target, ResourceSetWrapper container, UpdateOperations action) { if (container.ChangeInterceptors != null) { Dictionary <object, UpdateOperations> dictionary; UpdateOperations operations; if (!this.items.TryGetValue(container, out dictionary)) { if (this.service.Provider.IsV1Provider) { dictionary = new Dictionary <object, UpdateOperations>(EqualityComparer <object> .Default); } else { dictionary = new Dictionary <object, UpdateOperations>(ReferenceEqualityComparer <object> .Instance); } this.items.Add(container, dictionary); } if (dictionary.TryGetValue(target, out operations)) { if ((action | operations) != operations) { dictionary[target] = action | operations; } } else { dictionary.Add(target, action); } } }
internal RequestDescription UpdateVersions(string acceptTypesText, ResourceSetWrapper resourceSet, IDataService service) { DataServiceHostWrapper host = service.OperationContext.Host; if ((host.HttpVerb == HttpVerbs.GET) || ((host.HttpVerb == HttpVerbs.POST) && (this.TargetSource == RequestTargetSource.ServiceOperation))) { if (this.TargetKind == RequestTargetKind.Resource) { if (!this.LinkUri) { this.InitializeVersion(service.OperationContext); bool considerEpmInVersion = WebUtil.IsAtomResponseFormat(acceptTypesText, this.TargetKind, service.Configuration.DataServiceBehavior.MaxProtocolVersion, this.requestMaxVersion); Version version = resourceSet.MinimumResponsePayloadVersion(service, considerEpmInVersion); this.VerifyAndRaiseResponseVersion(version, service); } } else if (((this.TargetResourceType != null) && (this.CountOption != RequestQueryCountOption.ValueOnly)) && (this.TargetKind != RequestTargetKind.MediaResource)) { this.VerifyAndRaiseResponseVersion(this.TargetResourceType.MetadataVersion, service); } else if (this.TargetKind == RequestTargetKind.OpenProperty) { this.InitializeVersion(service.OperationContext); Version effectiveMaxResponseVersion = WebUtil.GetEffectiveMaxResponseVersion(service.Configuration.DataServiceBehavior.MaxProtocolVersion, this.requestMaxVersion); this.VerifyAndRaiseResponseVersion(effectiveMaxResponseVersion, service); } } else if (host.HttpVerb == HttpVerbs.PATCH) { this.VerifyProtocolVersion(Version3Dot0, service); this.VerifyRequestVersion(Version3Dot0, service); } return(this); }
/// <summary> /// Create a new request description from the given request description and new entity as the result. /// </summary> /// <param name="description">Existing request description.</param> /// <param name="entity">entity that needs to be the result of the new request.</param> /// <param name="container">container to which the entity belongs to.</param> /// <returns>a new instance of request description containing information about the given entity.</returns> internal static RequestDescription CreateSingleResultRequestDescription( RequestDescription description, object entity, ResourceSetWrapper container) { // Create a new request description for the results that will be returned. SegmentInfo segmentInfo = new SegmentInfo(); segmentInfo.RequestEnumerable = new object[] { entity }; segmentInfo.TargetKind = description.TargetKind; segmentInfo.TargetSource = description.TargetSource; segmentInfo.SingleResult = true; segmentInfo.ProjectedProperty = description.Property; segmentInfo.TargetResourceType = container != null ? container.ResourceType : null; segmentInfo.TargetContainer = container; segmentInfo.Identifier = description.LastSegmentInfo.Identifier; #if DEBUG segmentInfo.AssertValid(); #endif SegmentInfo[] segmentInfos = description.SegmentInfos; segmentInfos[segmentInfos.Length - 1] = segmentInfo; RequestDescription resultDescription = new RequestDescription( segmentInfos, container != null ? container.Name : null, description.UsesContainerName, description.MimeType, description.ResultUri); resultDescription.requireMinimumVersion = description.RequireMinimumVersion; resultDescription.responseVersion = description.ResponseVersion; resultDescription.maxFeatureVersion = description.MaxFeatureVersion; return(resultDescription); }
private void ApplyNavigationProperty(ODataNavigationLink navigationLink, ResourceSetWrapper entityResourceSet, ResourceType entityResourceType, ResourceProperty navigationProperty, object entityResource) { ResourceSetWrapper targetResourceSet = null; targetResourceSet = this.GetNavigationPropertyTargetResourceSet(entityResourceSet, entityResourceType, navigationProperty); foreach (ODataItem item in navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>()) { ODataEntityReferenceLink entityReferenceLink = item as ODataEntityReferenceLink; if (entityReferenceLink != null) { this.ApplyEntityReferenceLinkInNavigationProperty(navigationProperty, entityResource, entityReferenceLink); } else { ODataFeed feed = item as ODataFeed; if (feed != null) { this.ApplyFeedInNavigationProperty(navigationProperty, targetResourceSet, entityResource, feed); } else { ODataEntry entry = (ODataEntry)item; this.ApplyEntryInNavigationProperty(navigationProperty, targetResourceSet, entityResource, entry); } } } }
public void Init() { this.entityType = new ResourceType(typeof(object), ResourceTypeKind.EntityType, null, "Fake.NS", "Type", false) { CanReflectOnInstanceType = false }; this.entityType.AddProperty(new ResourceProperty("Id", ResourcePropertyKind.Key | ResourcePropertyKind.Primitive, ResourceType.GetPrimitiveResourceType(typeof(int))) { CanReflectOnInstanceTypeProperty = false }); this.entityType.SetReadOnly(); var resourceSet = new ResourceSet("Set", this.entityType); resourceSet.SetReadOnly(); this.resourceSetWrapper = ResourceSetWrapper.CreateForTests(resourceSet); this.action = new ServiceAction("Fake", ResourceType.GetPrimitiveResourceType(typeof(int)), OperationParameterBindingKind.Sometimes, new[] { new ServiceActionParameter("p1", this.entityType) }, null); this.action.SetReadOnly(); this.provider = new TestDataServiceProvider(); this.actionProvider = DataServiceActionProviderWrapper.Create(this.provider, ODataProtocolVersion.V4, () => this.operationContext); var host = new DataServiceHostSimulator(); this.operationContext = new DataServiceOperationContext(host); this.operationContext.InitializeAndCacheHeaders(new DataServiceSimulator()); }
internal static void CheckResourceRights(ResourceSetWrapper container, EntitySetRights requiredRights) { if ((requiredRights & container.Rights) == EntitySetRights.None) { throw DataServiceException.CreateForbidden(); } }
/// <summary> /// Raise the feature version if the target container contains any type with FF mapped properties that is KeepInContent=false. /// </summary> /// <param name="service">service instance</param> /// <returns>This RequestDescription instance</returns> internal RequestDescription UpdateAndCheckEpmFeatureVersion(IDataService service) { Debug.Assert(this.LastSegmentInfo != null, "this.LastSegmentInfo != null"); if (this.LinkUri) { // For $link operations we raise the feature version if either side of $link points to a set that // is not V1 compatible. ResourceSetWrapper leftSet; ResourceSetWrapper rightSet; this.GetLinkedResourceSets(out leftSet, out rightSet); Debug.Assert(leftSet != null, "leftSet != null"); Debug.Assert(rightSet != null, "rightSet != null"); this.UpdateAndCheckEpmFeatureVersion(leftSet, service); this.UpdateAndCheckEpmFeatureVersion(rightSet, service); } else { // The last segment might not be a resource. Trace backward to find the target entity resource. int resourceIndex = this.GetIndexOfTargetEntityResource(); // Not every request has a target resource. Service Operations for example can return just primitives. if (resourceIndex != -1) { ResourceSetWrapper resourceSet = this.SegmentInfos[resourceIndex].TargetContainer; Debug.Assert(resourceSet != null, "resourceSet != null"); this.UpdateAndCheckEpmFeatureVersion(resourceSet, service); } } return(this); }
/// <summary>Gets a string with methods allowed on the target for the <paramref name="description"/>.</summary> /// <param name="configuration">configuration object which has the data</param> /// <param name="description">Description with target.</param> /// <returns>A string with methods allowed on the description; possibly null.</returns> internal static string GetAllowedMethods(DataServiceConfiguration configuration, RequestDescription description) { Debug.Assert(description != null, "description != null"); Debug.Assert( description.TargetKind != RequestTargetKind.Nothing, "description.TargetKind != RequestTargetKind.Void - otherwise it hasn't been determined yet"); Debug.Assert( description.TargetKind != RequestTargetKind.VoidOperation, "description.TargetKind != RequestTargetKind.VoidOperation - this method is only for containers"); if (description.TargetKind == RequestTargetKind.Metadata || description.TargetKind == RequestTargetKind.ServiceDirectory) { return(XmlConstants.HttpMethodGet); } if (description.TargetKind == RequestTargetKind.Batch) { return(XmlConstants.HttpMethodPost); } int index = description.GetIndexOfTargetEntityResource(); Debug.Assert(index >= 0 && index < description.SegmentInfos.Count, "index >=0 && index <description.SegmentInfos.Count"); ResourceSetWrapper container = description.SegmentInfos[index].TargetResourceSet; return(GetAllowedMethods(configuration, container, description)); }
/// <summary>Checks whether this request has the specified reading rights.</summary> /// <param name="container">Container to check.</param> /// <param name="singleResult">Whether a single or multiple resources are requested.</param> /// <exception cref="DataServiceException">Thrown if <paramref name="singleResult"/> aren't available.</exception> internal static void CheckResourceRightsForRead(ResourceSetWrapper container, bool singleResult) { Debug.Assert(container != null, "container != null"); EntitySetRights requiredRights = singleResult ? EntitySetRights.ReadSingle : EntitySetRights.ReadMultiple; CheckResourceRights(container, requiredRights); }
/// <summary> /// Applies a navigation link as a navigation property. /// </summary> /// <param name="navigationLink">The navigation link read from the payload to apply.</param> /// <param name="entityResourceSet">The resource set into which the entity belongs to.</param> /// <param name="entityResourceType">The type of the entity to apply the properties to.</param> /// <param name="navigationProperty">The navigation property which coresponds with the navigation link.</param> /// <param name="entityResource">The entity resource to apply the properties to.</param> private void ApplyNavigationProperty( ODataNavigationLink navigationLink, ResourceSetWrapper entityResourceSet, ResourceType entityResourceType, ResourceProperty navigationProperty, object entityResource) { Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert(entityResourceSet != null, "entityResourceSet != null"); Debug.Assert(entityResourceType != null, "entityResourceType != null"); Debug.Assert(entityResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "Only entity types can be specified for entities."); Debug.Assert(navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType, "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType"); Debug.Assert(navigationLink.Name == navigationProperty.Name, "The navigationProperty must have the same name as the navigationLink to apply."); Debug.Assert(entityResource != null, "entityResource != null"); ResourceSetWrapper targetResourceSet = null; // Get the target resource set for the navigation property, this also causes validation of the resource set and thus migth fail. // WCF DS Used to do this in ATOM only if the link was expanded, which was a security issue we decided to fix, so now we do it always. targetResourceSet = this.GetNavigationPropertyTargetResourceSet(entityResourceSet, entityResourceType, navigationProperty); ODataNavigationLinkAnnotation navigationLinkAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(navigationLinkAnnotation != null, "navigationLinkAnnotation != null"); Debug.Assert(navigationLinkAnnotation.Count > 0, "Each navigation link must have at least one child in request."); Debug.Assert(navigationLink.IsCollection.HasValue, "We should know the cardinality of the navigation link by now."); // We have to allow IsCollection=false for ResourceSetReference properties as well. Debug.Assert( navigationLink.IsCollection == true || (navigationLinkAnnotation.Count == 1), "If the navigation link is a singleton, then there must be exactly one child in it and the property must be a singleton as well."); Debug.Assert( navigationLink.IsCollection == false || (navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference), "If the navigation link is a collection, then the property must be a collection as well."); // Just loop through the navigation link content // Note that if the navigation link is a singleton it must have just one item in it, so it's OK to loop anyway. foreach (ODataItem childItem in navigationLinkAnnotation) { ODataEntityReferenceLink entityReferenceLink = childItem as ODataEntityReferenceLink; if (entityReferenceLink != null) { this.ApplyEntityReferenceLinkInNavigationProperty(navigationProperty, entityResource, entityReferenceLink); continue; } ODataFeed feed = childItem as ODataFeed; if (feed != null) { this.ApplyFeedInNavigationProperty(navigationProperty, targetResourceSet, entityResource, feed); continue; } // It must be entry by now. ODataEntry entry = (ODataEntry)childItem; this.ApplyEntryInNavigationProperty(navigationProperty, targetResourceSet, entityResource, entry); } }
/// <summary> /// Initializes a new instance of the <see cref="Microsoft.OData.Service.ExpandAndSelectParseResult"/> class. /// </summary> /// <param name="requestDescription">The request description.</param> /// <param name="dataService">The data service.</param> internal ExpandAndSelectParseResult(RequestDescription requestDescription, IDataService dataService) { Debug.Assert(dataService != null, "dataService != null"); Debug.Assert(dataService.OperationContext != null, "dataService.OperationContext != null"); Debug.Assert(dataService.OperationContext.RequestMessage != null, "dataService.OperationContext.RequestMessage != null"); string expand = dataService.OperationContext.RequestMessage.GetQueryStringItem(XmlConstants.HttpQueryStringExpand); this.RawSelectQueryOptionValue = dataService.OperationContext.RequestMessage.GetQueryStringItem(XmlConstants.HttpQueryStringSelect); ResourceType targetResourceType = requestDescription.TargetResourceType; ResourceSetWrapper targetResourceSet = requestDescription.TargetResourceSet; if (!string.IsNullOrEmpty(expand)) { if (targetResourceType == null || targetResourceType.ResourceTypeKind != ResourceTypeKind.EntityType || targetResourceSet == null) { throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryExpandOptionNotApplicable); } } if (!string.IsNullOrEmpty(this.RawSelectQueryOptionValue)) { ValidateSelectIsAllowedForRequest(requestDescription); // Throw if $select requests have been disabled by the user Debug.Assert(dataService.Configuration != null, "dataService.Configuration != null"); if (!dataService.Configuration.DataServiceBehavior.AcceptProjectionRequests) { throw DataServiceException.CreateBadRequestError(Strings.DataServiceConfiguration_ProjectionsNotAccepted); } } MetadataProviderEdmModel model = dataService.Provider.GetMetadataProviderEdmModel(); var uriParser = RequestUriProcessor.CreateUriParserWithBatchReferenceCallback(dataService, dataService.OperationContext.AbsoluteRequestUri); try { Debug.Assert(model.Mode == MetadataProviderEdmModelMode.Serialization, "Model expected to be in serialization mode by default"); model.Mode = MetadataProviderEdmModelMode.SelectAndExpandParsing; this.Clause = uriParser.ParseSelectAndExpand(); } catch (ODataException ex) { throw new DataServiceException(400, null, ex.Message, null, ex); } finally { model.Mode = MetadataProviderEdmModelMode.Serialization; } if (this.Clause != null) { this.HasExpand = this.Clause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Any(); this.HasSelect = HasSelectedItemAtAnyLevel(this.Clause); } }
private void ApplyNavigationProperties(ODataEntryAnnotation entryAnnotation, ResourceSetWrapper entityResourceSet, ResourceType entityResourceType, object entityResource) { foreach (ODataNavigationLink link in entryAnnotation) { ResourcePropertyKind stream = ResourcePropertyKind.Stream; ResourceProperty navigationProperty = entityResourceType.TryResolvePropertyName(link.Name, stream); this.ApplyNavigationProperty(link, entityResourceSet, entityResourceType, navigationProperty, entityResource); } }
public void WriteComplexColParameter_WithEmptyCollection() { ResourceSetWrapper resourceSet = new ResourceSetWrapper() { ResourceSet = new ODataResourceSet() }; WriteParameter(resourceSet, true, (actual) => Assert.Equal("[]", actual)); WriteParameter(resourceSet, false, (actual) => Assert.Equal("[]", actual)); }
/// <summary>Checks whether this request has the specified rights.</summary> /// <param name="container">Container to check.</param> /// <param name="requiredRights">Required rights.</param> /// <exception cref="DataServiceException">Thrown if <paramref name="requiredRights"/> aren't available.</exception> internal static void CheckResourceRights(ResourceSetWrapper container, EntitySetRights requiredRights) { Debug.Assert(container != null, "container != null"); Debug.Assert(requiredRights != EntitySetRights.None, "requiredRights != EntitySetRights.None"); if ((requiredRights & container.Rights) == 0) { throw DataServiceException.CreateForbidden(); } }
public void WriteComplexColParameter_WithEmptyCollection() { ResourceSetWrapper resourceSet = new ResourceSetWrapper() { ResourceSet = new ODataResourceSet() }; WriteParameter(resourceSet, true, (actual) => actual.Should().Be("[]")); WriteParameter(resourceSet, false, (actual) => actual.Should().Be("[]")); }
protected bool PushSegmentForProperty(ResourceProperty property, ResourceType currentResourceType, ExpandedProjectionNode expandedProjectionNode) { ResourceSetWrapper currentContainer = this.CurrentContainer; if (currentContainer != null) { currentContainer = this.service.Provider.GetContainer(currentContainer, currentResourceType, property); } return(this.PushSegment(currentContainer, expandedProjectionNode)); }
private ResourceSetWrapper GetNavigationPropertyTargetResourceSet(ResourceSetWrapper parentResourceSet, ResourceType parentResourceType, ResourceProperty navigationProperty) { ResourceSetWrapper resourceSet = base.Service.Provider.GetContainer(parentResourceSet, parentResourceType, navigationProperty); if (resourceSet == null) { throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_InvalidPropertyNameSpecified(navigationProperty.Name, parentResourceType.FullName)); } base.RequestDescription.UpdateAndCheckEpmFeatureVersion(resourceSet, base.Service); return(resourceSet); }
internal ExpandSegment(string name, Expression filter, int maxResultsExpected, ResourceSetWrapper container, ResourceType targetResourceType, ResourceProperty expandedProperty, System.Data.Services.Providers.OrderingInfo orderingInfo) { WebUtil.CheckArgumentNull <string>(name, "name"); CheckFilterType(filter); this.name = name; this.filter = filter; this.container = container; this.maxResultsExpected = maxResultsExpected; this.expandedProperty = expandedProperty; this.orderingInfo = orderingInfo; this.targetResourceType = targetResourceType; }
/// <summary> /// Handle the navigation properties as specified in the payload /// </summary> /// <param name="parentResourceSet">resource set where <paramref name="resource"/> belongs to</param> /// <param name="parentResourceType">resource type declaring the navigation property.</param> /// <param name="resource">instance of the resource declaring the navigation property.</param> /// <param name="resourceProperty">resource property containing metadata about the navigation property.</param> /// <param name="propertyValue">value of the navigation property.</param> private void HandleNavigationProperty(ResourceSetWrapper parentResourceSet, ResourceType parentResourceType, object resource, ResourceProperty resourceProperty, object propertyValue) { Debug.Assert(parentResourceSet != null, "parentResourceSet != null"); Debug.Assert(parentResourceType != null, "parentResourceType != null"); Debug.Assert(resourceProperty != null && resourceProperty.TypeKind == ResourceTypeKind.EntityType, "its must be a nav property"); bool existingRelationship; Deserializer.CheckForBindingInPutOperations(this.Service.OperationContext.Host.AstoriaHttpVerb); ResourceSetWrapper propertySet = this.Service.Provider.GetContainer(parentResourceSet, parentResourceType, resourceProperty); if (propertySet == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(resourceProperty.Name, parentResourceType.FullName)); } // FeatureVersion needs to be 2.0 if any of the property in the types contained in the resource set has KeepInContent false this.RequestDescription.UpdateAndCheckEpmFeatureVersion(propertySet, this.Service); if (resourceProperty.Kind == ResourcePropertyKind.ResourceReference) { SegmentInfo segmentInfo = CreateSegment(resourceProperty, resourceProperty.Name, propertySet, true /* singleResult */); segmentInfo.TargetKind = RequestTargetKind.Resource; // For navigation property, allow both inserts and binding in this case propertyValue = this.CreateObject(propertyValue, segmentInfo, false /*topLevel*/, out existingRelationship); if (!existingRelationship) { this.Updatable.SetReference(resource, resourceProperty.Name, propertyValue); } } else if (resourceProperty.Kind == ResourcePropertyKind.ResourceSetReference) { if (propertyValue == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_CannotSetCollectionsToNull(resourceProperty.Name)); } ArrayList resourceCollection = GetArrayList(propertyValue); SegmentInfo segmentInfo = CreateSegment(resourceProperty, resourceProperty.Name, propertySet, true /* singleResult */); foreach (object resourceObject in resourceCollection) { object resourceInstance = this.CreateObject(resourceObject, segmentInfo, false /*topLevel*/, out existingRelationship); Debug.Assert(resourceInstance != null, "resourceInstance != null"); if (!existingRelationship) { this.Updatable.AddReferenceToCollection(resource, resourceProperty.Name, resourceInstance); } } } }
private bool PushSegment(ResourceSetWrapper container, ExpandedProjectionNode expandedNode) { if (((this.service.Configuration.MaxResultsPerCollection == 0x7fffffff) && ((container == null) || (container.PageSize == 0))) && ((this.requestDescription.RootProjectionNode == null) && !this.IsCustomPaged)) { return(false); } if (this.segmentInfo == null) { this.segmentInfo = new SegmentInfo(); } this.segmentInfo.PushSegment(container, expandedNode); return(true); }
/// <summary> /// Raise the feature version if the given set contains any type with FF mapped properties that is KeepInContent=false. /// </summary> /// <param name="resourceSet">Resource set to test</param> /// <param name="service">service instance</param> /// <returns>This RequestDescription instance</returns> internal RequestDescription UpdateAndCheckEpmFeatureVersion(ResourceSetWrapper resourceSet, IDataService service) { Debug.Assert(resourceSet != null, "resourceSet != null"); Debug.Assert(service != null, "provider != null"); // For feature version we only look at the SET, and bump the version if it's not V1 compatible. We do this even if the // target kind is not Resource. So we could have request and response DSV be 1.0 while feature version be 2.0. if (!resourceSet.EpmIsV1Compatible(service.Provider)) { this.RaiseFeatureVersion(2, 0, service.Configuration); } return(this); }
/// <summary>Composes all query interceptors into a single expression.</summary> /// <param name="serviceInstance">Web service instance.</param> /// <param name="container">Container for which interceptors should run.</param> /// <returns>An expression the filter for query interceptors, possibly null.</returns> internal static Expression ComposeQueryInterceptors(object serviceInstance, ResourceSetWrapper container) { Debug.Assert(container != null, "container != null"); MethodInfo[] methods = container.QueryInterceptors; if (methods == null || methods.Length == 0) { return(null); } LambdaExpression filter = null; for (int i = 0; i < methods.Length; i++) { Expression predicate; try { predicate = (Expression)methods[i].Invoke(serviceInstance, WebUtil.EmptyObjectArray); } catch (TargetInvocationException tie) { ErrorHandler.HandleTargetInvocationException(tie); throw; } if (predicate == null) { throw new InvalidOperationException(Strings.DataService_AuthorizationReturnedNullQuery(methods[i].Name, methods[i].DeclaringType.FullName)); } // predicate is LambdaExpression -- otherwise signature check missed something and following cast would throw LambdaExpression lambdaPredicate = ((LambdaExpression)predicate); if (filter == null) { filter = lambdaPredicate; } else { ParameterExpression parameter = filter.Parameters[0]; Expression adjustedPredicate = ParameterReplacerVisitor.Replace( lambdaPredicate.Body, // expression lambdaPredicate.Parameters[0], // oldParameter parameter); // newParameter filter = Expression.Lambda(Expression.And(filter.Body, adjustedPredicate), parameter); } } return(filter); }
private void GetLinkedResourceSets(out ResourceSetWrapper leftSet, out ResourceSetWrapper rightSet) { int index = 0; while (index < this.segmentInfos.Length) { if (this.segmentInfos[index].TargetKind == RequestTargetKind.Link) { break; } index++; } leftSet = this.segmentInfos[index - 1].TargetContainer; rightSet = this.segmentInfos[index + 1].TargetContainer; }
internal static string GetAllowedMethods(DataServiceConfiguration configuration, RequestDescription description) { if ((description.TargetKind == RequestTargetKind.Metadata) || (description.TargetKind == RequestTargetKind.ServiceDirectory)) { return("GET"); } if (description.TargetKind == RequestTargetKind.Batch) { return("POST"); } int indexOfTargetEntityResource = description.GetIndexOfTargetEntityResource(); ResourceSetWrapper targetContainer = description.SegmentInfos[indexOfTargetEntityResource].TargetContainer; return(GetAllowedMethods(configuration, targetContainer, description)); }
/// <summary> /// Gets a target resource set for the specified navigation property. /// </summary> /// <param name="parentResourceSet">The resource set of the entity on which the navigation property is accessed.</param> /// <param name="parentResourceType">The resourec type of the entity on which the navigation property is accessed.</param> /// <param name="navigationProperty">The navigation property to access.</param> /// <returns>The target resource set of the navigation property.</returns> /// <remarks>This method validates that the resource set is accessible and it performs appropriate version checks.</remarks> private ResourceSetWrapper GetNavigationPropertyTargetResourceSet(ResourceSetWrapper parentResourceSet, ResourceType parentResourceType, ResourceProperty navigationProperty) { Debug.Assert(parentResourceSet != null, "parentResourceSet != null"); Debug.Assert(parentResourceType != null, "parentResourceType != null"); Debug.Assert(navigationProperty != null, "navigationProperty != null"); ResourceSetWrapper targetResourceSet = this.Service.Provider.GetResourceSet(parentResourceSet, parentResourceType, navigationProperty); if (targetResourceSet == null) { throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_InvalidPropertyNameSpecified(navigationProperty.Name, parentResourceType.FullName)); } return(targetResourceSet); }
private void WriteResourceSet(ODataWriter odataWriter, ResourceSetWrapper resourceSet) { odataWriter.WriteStart(resourceSet.ResourceSet); var resources = resourceSet.Resources; if (resources != null && resources.Count > 0) { foreach (var resource in resources) { WriteResource(odataWriter, resource); } } odataWriter.WriteEnd(); }