Example #1
0
        protected object GetObjectFromSegmentInfo(ResourceType resourceType, System.Data.Services.SegmentInfo segmentInfo, bool verifyETag, bool checkForNull, bool replaceResource)
        {
            object crossReferencedResource;

            if (segmentInfo.RequestExpression == null)
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_ResourceCanBeCrossReferencedOnlyForBindOperation);
            }
            if (IsCrossReferencedSegment(segmentInfo, this.service))
            {
                crossReferencedResource = GetCrossReferencedResource(segmentInfo);
            }
            else
            {
                crossReferencedResource = GetResource(segmentInfo, (resourceType != null) ? resourceType.FullName : null, this.Service, checkForNull);
                if (verifyETag)
                {
                    this.service.Updatable.SetETagValues(crossReferencedResource, segmentInfo.TargetContainer);
                }
            }
            if (replaceResource)
            {
                crossReferencedResource = this.Updatable.ResetResource(crossReferencedResource);
                WebUtil.CheckResourceExists(crossReferencedResource != null, segmentInfo.Identifier);
            }
            return(crossReferencedResource);
        }
Example #2
0
        private void SetResourceReferenceToUrl(object entityResource, ResourceProperty navigationProperty, string url)
        {
            base.CheckAndIncrementObjectCount();
            RequestDescription description = RequestUriProcessor.ProcessRequestUri(RequestUriProcessor.GetAbsoluteUriFromReference(url, base.Service.OperationContext), base.Service, true);

            if ((this.ContentFormat == ContentFormat.Atom) && !description.IsSingleResult)
            {
                if ((navigationProperty != null) && (navigationProperty.Kind == ResourcePropertyKind.ResourceReference))
                {
                    throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_LinkHrefMustReferToSingleResource(navigationProperty.Name));
                }
            }
            else
            {
                object propertyValue = base.Service.GetResource(description, description.SegmentInfos.Length - 1, null);
                if (navigationProperty.Kind == ResourcePropertyKind.ResourceReference)
                {
                    base.Updatable.SetReference(entityResource, navigationProperty.Name, propertyValue);
                }
                else
                {
                    WebUtil.CheckResourceExists(propertyValue != null, description.LastSegmentInfo.Identifier);
                    base.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, propertyValue);
                }
            }
        }
        /// <summary>
        /// Creates a new segment for an open property.
        /// </summary>
        /// <param name="previous">previous segment info.</param>
        /// <param name="identifier">name of the segment.</param>
        /// <returns>new open property segment.</returns>
        private static SegmentInfo CreateOpenPropertySegment(SegmentInfo previous, string identifier)
        {
            SegmentInfo segment = new SegmentInfo {
                Identifier = identifier
            };

            // Handle an open type property. If the current leaf isn't an
            // object (which implies it's already an open type), then
            // it should be marked as an open type.
            if (previous.TargetResourceType != null)
            {
                WebUtil.CheckResourceExists(previous.TargetResourceType.IsOpenType, segment.Identifier);
            }

            // Open navigation properties are not supported on OpenTypes.  We should throw on the following cases:
            // 1. the segment before $ref is always a navigation property pointing to a resource
            // 2. if the segment hasQuery, it is pointing to a resource
            // 3. if this is a POST operation, the target has to be either a set of links or an entity set
            if (previous.TargetKind == RequestTargetKind.Link)
            {
                throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(segment.Identifier));
            }

            segment.TargetSource       = RequestTargetSource.Property;
            segment.TargetResourceType = null;
            segment.TargetKind         = RequestTargetKind.OpenProperty;
            segment.SingleResult       = true;
            return(segment);
        }
        public static IDataServiceInvokable CreateServiceActionInvokable(DataServiceOperationContext operationContext, IDataServiceActionProvider actionProvider, ServiceAction serviceAction, object[] parameterTokens)
        {
            WebUtil.CheckArgumentNull <DataServiceOperationContext>(operationContext, "operationContext");
            WebUtil.CheckArgumentNull <IDataServiceActionProvider>(actionProvider, "actionProvider");
            WebUtil.CheckArgumentNull <ServiceAction>(serviceAction, "serviceAction");
            IDataServiceInvokable invokable = actionProvider.CreateInvokable(operationContext, serviceAction, parameterTokens);

            WebUtil.CheckResourceExists(invokable != null, serviceAction.Name);
            return(invokable);
        }
Example #5
0
        protected object GetTargetResourceToBind(Uri referencedUri, bool checkNull)
        {
            System.Data.Services.RequestDescription description = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service, true);
            object obj2 = this.Service.GetResource(description, description.SegmentInfos.Length - 1, null);

            if (checkNull)
            {
                WebUtil.CheckResourceExists(obj2 != null, description.LastSegmentInfo.Identifier);
            }
            return(obj2);
        }
Example #6
0
        public ConstantExpression GetQueryRootForResourceSet(ResourceSetWrapper resourceSet, DataServiceOperationContext operationContext)
        {
            IQueryable queryRootForResourceSet = this.queryProvider.GetQueryRootForResourceSet(resourceSet.ResourceSet);

            WebUtil.CheckResourceExists(queryRootForResourceSet != null, resourceSet.Name);
            if (!resourceSet.QueryRootType.IsAssignableFrom(queryRootForResourceSet.GetType()))
            {
                throw new InvalidOperationException(System.Data.Services.Strings.DataServiceProviderWrapper_InvalidQueryRootType(resourceSet.Name, resourceSet.QueryRootType.FullName));
            }
            return(Expression.Constant(queryRootForResourceSet));
        }
Example #7
0
        public static IDataServiceInvokable CreateServiceActionInvokable(DataServiceOperationContext operationContext, IDataServiceActionProvider actionProvider, ServiceAction serviceAction, object[] parameterTokens)
        {
            WebUtil.CheckArgumentNull(operationContext, "operationContext");
            WebUtil.CheckArgumentNull(actionProvider, "actionProvider");
            WebUtil.CheckArgumentNull(serviceAction, "serviceAction");

            operationContext.CurrentDataService.ProcessingPipeline.AssertAndUpdateDebugStateAtInvokeServiceAction(operationContext.CurrentDataService);

            IDataServiceInvokable result = actionProvider.CreateInvokable(operationContext, serviceAction, parameterTokens);

            WebUtil.CheckResourceExists(result != null, serviceAction.Name);
            return(result);
        }
        internal static QueryResultInfo GetSingleResultFromRequest(SegmentInfo segmentInfo)
        {
            Debug.Assert(segmentInfo != null && segmentInfo.RequestEnumerable != null, "segmentInfo != null && segmentInfo.RequestEnumerable != null");
            var queryResults = new QueryResultInfo(segmentInfo.RequestEnumerable);

            try
            {
                WebUtil.CheckResourceExists(queryResults.MoveNext(), segmentInfo.Identifier);
                WebUtil.CheckNullDirectReference(queryResults.Current, segmentInfo);
                return(queryResults);
            }
            catch
            {
                // Dispose the Enumerator in case of error
                WebUtil.Dispose(queryResults);
                throw;
            }
        }
Example #9
0
        /// <summary>
        /// Sets a resource reference to resource referenced by a URL.
        /// </summary>
        /// <param name="entityResource">The entity resource to set the resource reference on.</param>
        /// <param name="navigationProperty">The navigation property for which to set the reference to null.</param>
        /// <param name="url">The URL which points to the resource to set as the value of the navigation property.</param>
        private void SetResourceReferenceToUrl(object entityResource, ResourceProperty navigationProperty, string url)
        {
            Debug.Assert(entityResource != null, "entityResource != null");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            // Update the object count when you are performing a bind operation.
            this.CheckAndIncrementObjectCount();

            // Get the referenced resource.
            Uri referencedUri = RequestUriProcessor.GetAbsoluteUriFromReference(url, this.Service.OperationContext);
            RequestDescription requestDescription = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service, true /*internalQuery*/);

            // ATOM deserializer checks that the url doesn't point to a collection. If it does it will ignore the link.
            if (this.IsAtomRequest && !requestDescription.IsSingleResult)
            {
                if (navigationProperty != null &&
                    navigationProperty.Kind == ResourcePropertyKind.ResourceReference)
                {
                    throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_LinkHrefMustReferToSingleResource(navigationProperty.Name));
                }

                return;
            }

            // Get the resource
            object referencedResource = this.Service.GetResource(requestDescription, requestDescription.SegmentInfos.Count - 1, null);

            if (navigationProperty.Kind == ResourcePropertyKind.ResourceReference)
            {
                this.Updatable.SetReference(entityResource, navigationProperty.Name, referencedResource);
            }
            else
            {
                Debug.Assert(navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference, "Only navigation properties are allowed in this method.");

                // If we are to set the resource to a collection property it must not be null (so check for nulls), otherwise do allow nulls for backward compatibility.
                WebUtil.CheckResourceExists(referencedResource != null, requestDescription.LastSegmentInfo.Identifier);
                this.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, referencedResource);
            }
        }
Example #10
0
        internal static IEnumerator GetSingleResultFromRequest(SegmentInfo segmentInfo)
        {
            IEnumerator enumerator2;
            IEnumerator requestEnumerator = WebUtil.GetRequestEnumerator(segmentInfo.RequestEnumerable);
            bool        flag = true;

            try
            {
                WebUtil.CheckResourceExists(requestEnumerator.MoveNext(), segmentInfo.Identifier);
                RequestDescription.CheckNullDirectReference(requestEnumerator.Current, segmentInfo);
                flag        = false;
                enumerator2 = requestEnumerator;
            }
            finally
            {
                if (flag)
                {
                    WebUtil.Dispose(requestEnumerator);
                }
            }
            return(enumerator2);
        }
        /// <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);
        }
Example #12
0
        /// <summary>Applies the information from a link to the specified resource.</summary>
        /// <param name='link'>LinkDescriptor with information to apply.</param>
        /// <param name="resourceSet">Set for the target resource.</param>
        /// <param name='resourceType'>Type for the target resource.</param>
        /// <param name='resource'>Target resource to which information will be applied.</param>
        /// <param name="propertyName">Name of the property that this link represents.</param>
        private void ApplyLink(SyndicationLink link, ResourceSetWrapper resourceSet, ResourceType resourceType, object resource, string propertyName)
        {
            Debug.Assert(link != null, "link != null");
            Debug.Assert(resourceType != null, "resourceType != null");
            Debug.Assert(resource != null, "resource != null");

            ResourceProperty property = resourceType.TryResolvePropertyName(propertyName);

            if (property == null)
            {
                // Open navigation properties are not supported on OpenTypes
                throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(propertyName));
            }

            if (property.TypeKind != ResourceTypeKind.EntityType)
            {
                throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidNavigationPropertyName(propertyName, resourceType.FullName));
            }

            string      typeParameterValue = ValidateTypeParameterForNonOpenTypeProperties(link.MediaType, property);
            LinkContent linkContent        = this.HandleLinkContent(link, resource, resourceSet, resourceType, property, typeParameterValue, propertyName);

            #region Handle bind/unbind operation
            // If the href was specified empty or an empty inline element was specified, then we will set the
            // reference to null - this helps in overrriding if there was a default non-value for this property
            // else if only link element was specified, and then href points to a single result, then we will
            // perform a bind operation
            if ((linkContent == LinkContent.NoInlineElementSpecified && link.Uri != null && String.IsNullOrEmpty(link.Uri.OriginalString)) ||
                linkContent == LinkContent.EmptyInlineElementSpecified)
            {
                // update the object count when you are performing a bind operation
                this.CheckAndIncrementObjectCount();
                if (property != null && property.Kind == ResourcePropertyKind.ResourceSetReference)
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_CannotSetCollectionsToNull(propertyName));
                }

                // For open properties, we will assume that this is a reference property and set it to null
                this.Updatable.SetReference(resource, propertyName, null);
            }
            else if (linkContent == LinkContent.NoInlineElementSpecified && link.Uri != null && !String.IsNullOrEmpty(link.Uri.OriginalString))
            {
                // update the object count when you are performing a bind operation
                this.CheckAndIncrementObjectCount();

                // If the link points to a reference navigation property, then update the link
                Uri referencedUri = RequestUriProcessor.GetAbsoluteUriFromReference(link.Uri.OriginalString, this.Service.OperationContext);
                RequestDescription description = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service);
                if (!description.IsSingleResult)
                {
                    if (property != null && property.Kind == ResourcePropertyKind.ResourceReference)
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_LinkHrefMustReferToSingleResource(propertyName));
                    }

                    return;
                }

                // no need to check for null. For collection properties, they can never be null and that
                // check has been added below. For reference properties, if they are null, it means unbind
                // and hence no need to check for null.
                // Get the resource
                object targetResource = this.Service.GetResource(description, description.SegmentInfos.Length - 1, null);
                if (property.Kind == ResourcePropertyKind.ResourceReference)
                {
                    this.Updatable.SetReference(resource, propertyName, targetResource);
                }
                else
                {
                    WebUtil.CheckResourceExists(targetResource != null, description.LastSegmentInfo.Identifier);
                    this.Updatable.AddReferenceToCollection(resource, propertyName, targetResource);
                }
            }
            #endregion Handle bind/unbind operation
        }