public void FilterBySpatialFunctionWithLiterals() { Tuple <string, int>[] testCases = new Tuple <string, int>[] { Tuple.Create("eq 1", 4), Tuple.Create("ne 2", 4), Tuple.Create("gt 2", 0), }; this.serviceFactory.SetRequestUri("Entities"); string resourcePath = this.serviceFactory.RequestUri.OriginalString; foreach (var t in testCases) { this.serviceFactory.ClearQueryArgument(); this.serviceFactory.AddQueryArgument("$filter", "geo.distance(geography'SRID=1234;POINT(20 10)', geography'SRID=1234;POINT(20 10)') " + t.Item1); this.serviceFactory.SetRequestUri(resourcePath + "?$filter=geo.distance(geography'SRID=1234;POINT(20 10)', geography'SRID=1234;POINT(20 10)') " + t.Item1); var service = this.serviceFactory.CreateService(); RequestDescription d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); Action <GeographyPoint> verifyPoint = p => { Assert.AreEqual(20.0, p.Longitude); Assert.AreEqual(10.0, p.Latitude); }; RunSpatialDistanceFilterTest(d, verifyPoint, verifyPoint, 1.0, t.Item2); } }
private ODataStreamReferenceValue GetMediaResource(object element, ResourceType entityResourceType, string title, Uri relativeUri) { ODataStreamReferenceValue value2 = null; if (entityResourceType.IsMediaLinkEntry) { string str; Uri uri; string str2; base.Service.StreamProvider.GetStreamDescription(element, null, base.Service.OperationContext, out str, out uri, out str2); Uri uri2 = RequestUriProcessor.AppendEscapedSegment(relativeUri, "$value"); value2 = new ODataStreamReferenceValue { EditLink = uri2, ContentType = str2, ReadLink = uri ?? uri2 }; AtomStreamReferenceMetadata metadata2 = new AtomStreamReferenceMetadata(); AtomLinkMetadata metadata3 = new AtomLinkMetadata { Title = title }; metadata2.EditLink = metadata3; AtomStreamReferenceMetadata annotation = metadata2; value2.SetAnnotation <AtomStreamReferenceMetadata>(annotation); if (!string.IsNullOrEmpty(str)) { value2.ETag = str; } } return(value2); }
private void RunSpatialExpressionTest(string queryOption, string queryOptionValue, Expression <Func <IQueryable <TestEntityType>, IQueryable <TestEntityType> > > expectedExpressionPattern) { this.serviceFactory.SetRequestUri("Entities?" + queryOption + "=" + queryOptionValue); var service = this.serviceFactory.CreateService(); var d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); var actualQueryableMethodExpression = (MethodCallExpression)d.RequestExpression; var expectedString = expectedExpressionPattern.ToString(); var actualString = actualQueryableMethodExpression.ToString(); Console.WriteLine(); Console.WriteLine("Expected: " + expectedString); Console.WriteLine("Actual: " + actualString); // get the portion of the expected string which represents the 'root'. it will look something like 'q => q.' var parameterString = expectedExpressionPattern.Parameters.Single().ToString(); parameterString = parameterString + " => " + parameterString + "."; expectedString = expectedString.Substring(parameterString.Length); // just verify that the .Where or .OrderBy call matches. We don't verify the root of the tree. Assert.IsTrue(actualString.EndsWith(expectedString)); }
public void FilterCompareSpatialLiterals() { var tests = new[] { new { Operator = "eq", ErrorName = "Equal" }, new { Operator = "ne", ErrorName = "NotEqual" }, new { Operator = "lt", ErrorName = "LessThan" }, new { Operator = "gt", ErrorName = "GreaterThan" }, new { Operator = "le", ErrorName = "LessThanOrEqual" }, new { Operator = "ge", ErrorName = "GreaterThanOrEqual" } }; this.serviceFactory.SetRequestUri("Entities"); foreach (var test in tests) { // spatial literal vs spatial literal this.serviceFactory.SetRequestUri("Entities?$filter=geography'POINT(10 20)' " + test.Operator + " geography'SRID=1234;POINT(10 20)'"); var service = this.serviceFactory.CreateService(); Action processUri = () => RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); processUri.ShouldThrow <DataServiceException>().WithMessage(Microsoft.OData.Core.Strings.MetadataBinder_IncompatibleOperandsError("Edm.GeographyPoint", "Edm.GeographyPoint", test.ErrorName)); } }
/// <summary> /// Reads the input request payload and returns the WCF DS value representation of it. /// </summary> /// <param name="segmentInfo">Info about the request to read. For entity reference requests this is null.</param> /// <returns>The WCF DS representation of the value read. For entity reference link this is the Uri of the link.</returns> protected override object Read(SegmentInfo segmentInfo) { Debug.Assert(segmentInfo == null, "segmentInfo == null"); Debug.Assert(this.RequestDescription.LinkUri, "The EntityReferenceLinkDeserializer only supports $ref payloads."); ODataEntityReferenceLink entityReferenceLink = this.MessageReader.ReadEntityReferenceLink(); Debug.Assert(entityReferenceLink != null, "ReadEntityReferenceLink should never return null."); Uri entityReferenceUri = entityReferenceLink.Url; Debug.Assert(entityReferenceUri != null, "The Url of the entity reference link should never be null."); #pragma warning disable 618 AssertReaderFormatIsExpected(this.MessageReader, ODataFormat.Atom, ODataFormat.Json); #pragma warning restore 618 // We must fail on empty URI string entityReferenceUriAsString = UriUtil.UriToString(entityReferenceUri); if (string.IsNullOrEmpty(entityReferenceUriAsString)) { throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_MissingUriForLinkOperation); } // Resolve the URI against the service return(RequestUriProcessor.GetAbsoluteUriFromReference(entityReferenceUri, this.Service.OperationContext.AbsoluteServiceUri)); }
/// <summary> /// Get the ODataStreamReferenceValue instance containing the metadata for named stream property. /// </summary> /// <param name="entityToSerialize">Entity that is currently being serialized.</param> /// <param name="namedStreamProperty">Named stream property for which the link element needs to be written.</param> /// <returns> /// An instance of ODataStreamReferenceValue containing all the metadata about the named stream property. /// </returns> private ODataStreamReferenceValue GetNamedStreamPropertyValue(EntityToSerialize entityToSerialize, ResourceProperty namedStreamProperty) { Debug.Assert(entityToSerialize != null, "entityToSerialize != null"); Debug.Assert(namedStreamProperty != null, "namedStreamProperty != null"); Debug.Assert(namedStreamProperty.IsOfKind(ResourcePropertyKind.Stream), "namedStreamProperty.IsOfKind(ResourcePropertyKind.Stream)"); string mediaETag; Uri readStreamUri; string mediaContentType; this.Service.StreamProvider.GetStreamDescription(entityToSerialize.Entity, namedStreamProperty, this.Service.OperationContext, out mediaETag, out readStreamUri, out mediaContentType); Debug.Assert(WebUtil.IsETagValueValid(mediaETag, true), "WebUtil.IsETagValueValid(mediaETag, true)"); ODataStreamReferenceValue streamReferenceValue = new ODataStreamReferenceValue(); this.PayloadMetadataPropertyManager.SetContentType(streamReferenceValue, mediaContentType); this.PayloadMetadataPropertyManager.SetEditLink( streamReferenceValue, () => { Uri relativeUri = entityToSerialize.SerializedKey.RelativeEditLink; return(RequestUriProcessor.AppendUnescapedSegment(relativeUri, namedStreamProperty.Name)); }); if (!string.IsNullOrEmpty(mediaETag)) { this.PayloadMetadataPropertyManager.SetETag(streamReferenceValue, mediaETag); } // Note if readStreamUri is null, the self link for the named stream will be omitted. this.PayloadMetadataPropertyManager.SetReadLink(streamReferenceValue, () => readStreamUri); return(streamReferenceValue); }
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> /// Initializes a new dummy host for the batch request. /// This host represents a single operation in the batch. /// </summary> /// <param name="absoluteServiceUri">Absolute Uri to the service.</param> /// <param name="operationMessage">The request message representing a batch operation to wrap.</param> /// <param name="contentId">Content id for the given operation host.</param> /// <param name="writer">ODataBatchWriter instance.</param> /// <param name="odataMaxVersion">OData-MaxVersion header on the batch request. If the OData-MaxVersion header is not specified in the current operation, we default to the MaxDSV from the batch level.</param> internal BatchServiceHost(Uri absoluteServiceUri, IODataRequestMessage operationMessage, string contentId, ODataBatchWriter writer, Version odataMaxVersion) : this(writer) { Debug.Assert(absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri, "absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri"); Debug.Assert(operationMessage != null, "operationMessage != null"); this.absoluteServiceUri = absoluteServiceUri; this.absoluteRequestUri = RequestUriProcessor.GetAbsoluteUriFromReference(operationMessage.Url, absoluteServiceUri); this.requestHttpMethod = operationMessage.Method; this.contentId = contentId; foreach (KeyValuePair <string, string> header in operationMessage.Headers) { this.requestHeaders.Add(header.Key, header.Value); } // If the MaxDSV header is not specified in the current operation, we default to the MaxDSV from the batch level. if (string.IsNullOrEmpty(this.requestHeaders[XmlConstants.HttpODataMaxVersion])) { Debug.Assert(odataMaxVersion != null, "odataMaxVersion != null"); this.requestHeaders[XmlConstants.HttpODataMaxVersion] = odataMaxVersion.ToString(); } this.requestStream = operationMessage.GetStream(); }
public void FilterBySpatialFunctionWithProperties() { var testCases = new[] { Tuple.Create("eq 1", 4), Tuple.Create("ne 2", 4), Tuple.Create("gt 2", 0), }; foreach (var t in testCases) { this.serviceFactory.SetRequestUri("Entities?$filter=geo.distance(Point, geography'SRID=1234;POINT(20 10)') " + t.Item1); var service = this.serviceFactory.CreateService(); RequestDescription d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); Action <GeographyPoint> verifyPoint = p => { Assert.AreEqual(20.0, p.Longitude); Assert.AreEqual(10.0, p.Latitude); }; RunSpatialDistanceFilterTest(d, null, verifyPoint, 1.0, t.Item2); } }
private static ODataAssociationLink GetAssociationLink(Uri relativeUri, ResourceProperty navigationProperty) { Uri uri = RequestUriProcessor.AppendUnescapedSegment(RequestUriProcessor.AppendEscapedSegment(relativeUri, "$links"), navigationProperty.Name); return(new ODataAssociationLink { Name = navigationProperty.Name, Url = uri }); }
/// <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); } }
protected override object Read(System.Data.Services.SegmentInfo segmentInfo) { Uri url = base.MessageReader.ReadEntityReferenceLink().Url; if (string.IsNullOrEmpty(CommonUtil.UriToString(url))) { throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_MissingUriForLinkOperation); } return(RequestUriProcessor.GetAbsoluteUriFromReference(url, base.Service.OperationContext.AbsoluteServiceUri, base.RequestDescription.RequestVersion)); }
public void QuerySpatialProperty() { this.serviceFactory.SetRequestUri("Entities(0)/Spatial"); var service = this.serviceFactory.CreateService(); RequestDescription d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); Assert.AreEqual(RequestTargetKind.Primitive, d.LastSegmentInfo.TargetKind); Assert.AreEqual("Spatial", d.LastSegmentInfo.Identifier); }
/// <summary> /// Constructs a new instance of DataServiceOperationContext object /// </summary> /// <param name="host">RequestMessage instance for the current operation context.</param> internal DataServiceOperationContext(IDataServiceHost host) { Debug.Assert(host != null, "host != null"); this.hostInterface = host; this.lazyMetadataUri = new SimpleLazy <Uri>(() => { Debug.Assert(this.AbsoluteServiceUri != null, "Cannot get the metadata uri if the absolute service uri is not initialized"); return(RequestUriProcessor.AppendEscapedSegment(this.AbsoluteServiceUri, XmlConstants.UriMetadataSegment)); }); }
/// <summary>Initializes a new <see cref="RequestExpressionParser"/>.</summary> /// <param name="service">Service with data and configuration.</param> /// <param name="requestDescription">RequestDescription instance containing information about the current request being parsed.</param> internal RequestExpressionParser(IDataService service, RequestDescription requestDescription) { Debug.Assert(service != null, "service != null"); Debug.Assert(requestDescription != null, "requestDescription != null"); this.provider = service.Provider; this.model = this.provider.GetMetadataProviderEdmModel(); this.odataUriParser = RequestUriProcessor.CreateUriParserWithBatchReferenceCallback(service, service.OperationContext.AbsoluteRequestUri); }
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); }
internal static Uri GetIdAndEditLink(object resource, ResourceType resourceType, DataServiceProviderWrapper provider, ResourceSetWrapper container, Uri absoluteServiceUri, out Uri id) { string segmentIdentifier = GetObjectKey(resource, resourceType, provider, container.Name); Uri uri = RequestUriProcessor.AppendEscapedSegment(absoluteServiceUri, segmentIdentifier); id = uri; if (container.HasNavigationPropertyOrNamedStreamsOnDerivedTypes(provider)) { uri = RequestUriProcessor.AppendUnescapedSegment(uri, resourceType.FullName); } return(uri); }
/// <summary> /// Initializes a new instance of the <see cref="LazySerializedEntityKey"/> class which uses the same syntax for identity and edit link. /// </summary> /// <param name="lazyRelativeIdentity">The identity as a lazy string relative to the service URI.</param> /// <param name="absoluteServiceUri">The absolute service URI.</param> /// <param name="editLinkSuffix">The optional suffix to append to the edit link. Null means nothing will be appended.</param> internal LazySerializedEntityKey(SimpleLazy <string> lazyRelativeIdentity, Uri absoluteServiceUri, string editLinkSuffix) { Debug.Assert(absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri, "absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri"); this.lazyAbsoluteEditLinkWithoutSuffix = new SimpleLazy <Uri>(() => RequestUriProcessor.AppendEscapedSegment(absoluteServiceUri, lazyRelativeIdentity.Value)); this.lazyIdentity = new SimpleLazy <Uri>(() => this.lazyAbsoluteEditLinkWithoutSuffix.Value, false); this.lazyAbsoluteEditLink = AppendLazilyIfNeeded(this.lazyAbsoluteEditLinkWithoutSuffix, editLinkSuffix); SimpleLazy <Uri> relativeEdit = new SimpleLazy <Uri>(() => new Uri(lazyRelativeIdentity.Value, UriKind.Relative), false); this.lazyRelativeEditLink = AppendLazilyIfNeeded(relativeEdit, editLinkSuffix); }
/// <summary> /// Get the stream reference value for media resource (the default stream of an entity). /// </summary> /// <param name="entityToSerialize">Entity that is currently being serialized.</param> /// <param name="title">The title for the element being written.</param> /// <returns> /// An instance of ODataStreamReferenceValue containing the metadata about the media resource. /// </returns> private ODataStreamReferenceValue GetMediaResource(EntityToSerialize entityToSerialize, string title) { Debug.Assert(entityToSerialize.Entity != null, "element != null"); Debug.Assert(entityToSerialize.ResourceType != null && entityToSerialize.ResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "type != null && type.ResourceTypeKind == ResourceTypeKind.EntityType"); Debug.Assert(!string.IsNullOrEmpty(title), "!string.IsNullOrEmpty(title)"); ODataStreamReferenceValue mediaResource = null; // Handle MLE if (entityToSerialize.ResourceType.IsMediaLinkEntry) { string mediaETag; Uri readStreamUri; string mediaContentType; Debug.Assert(entityToSerialize.ResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "type.ResourceTypeKind == ResourceTypeKind.EntityType"); this.Service.StreamProvider.GetStreamDescription(entityToSerialize.Entity, null /*null for MLE*/, this.Service.OperationContext, out mediaETag, out readStreamUri, out mediaContentType); Debug.Assert(WebUtil.IsETagValueValid(mediaETag, true), "WebUtil.IsETagValueValid(mediaETag, true)"); Debug.Assert(!string.IsNullOrEmpty(mediaContentType), "!string.IsNullOrEmpty(mediaContentType)"); mediaResource = new ODataStreamReferenceValue(); // build the stream's edit link lazily to avoid creating the entity's edit link if it is not needed. SimpleLazy <Uri> lazyStreamEditLink = new SimpleLazy <Uri>(() => RequestUriProcessor.AppendEscapedSegment(entityToSerialize.SerializedKey.RelativeEditLink, XmlConstants.UriValueSegment)); this.PayloadMetadataPropertyManager.SetEditLink(mediaResource, () => lazyStreamEditLink.Value); this.PayloadMetadataPropertyManager.SetContentType(mediaResource, mediaContentType); // If the stream provider did not provider a read link, then we should use the edit link as the read link. this.PayloadMetadataPropertyManager.SetReadLink(mediaResource, () => readStreamUri ?? lazyStreamEditLink.Value); #pragma warning disable 618 if (this.contentFormat == ODataFormat.Atom) #pragma warning restore 618 { AtomStreamReferenceMetadata mediaResourceAtom = new AtomStreamReferenceMetadata() { EditLink = new AtomLinkMetadata { Title = title } }; mediaResource.SetAnnotation(mediaResourceAtom); } if (!string.IsNullOrEmpty(mediaETag)) { this.PayloadMetadataPropertyManager.SetETag(mediaResource, mediaETag); } } return(mediaResource); }
[Ignore] // Currently we have overloads of geog, geogPoint; etc. because EF forces us to use properties of type Geography rather than GeographyPoint. public void FilterBySpatialFunctionWrongType() { this.serviceFactory.SetRequestUri("Entities"); this.serviceFactory.AddQueryArgument("$filter", "geo.distance(Spatial, SRID=1234;POINT(10 20)) lt 10"); var service = this.serviceFactory.CreateService(); Action test = () => RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); string expectedFunctions = "geo.distance(System.Data.Spatial.Geography.GeographyPoint, System.Data.Spatial.Geography.GeographyPoint)"; test.ShouldThrow <DataServiceException>().WithMessage(Microsoft.OData.Service.Strings.RequestQueryParser_NoApplicableFunction( "geo.distance", expectedFunctions)); }
/// <summary> /// Initializes a new dummy host for the batch request. /// This host represents a single operation in the batch. /// </summary> /// <param name="absoluteServiceUri">absolute Uri to the service</param> /// <param name="batchStream">batch stream which contains the header information.</param> /// <param name="contentId">content id for the given operation host.</param> /// <param name='boundary'>Response separator string.</param> /// <param name='writer'>Output writer.</param> internal BatchServiceHost(Uri absoluteServiceUri, BatchStream batchStream, string contentId, string boundary, StreamWriter writer) : this(boundary, writer) { Debug.Assert(absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri, "absoluteServiceUri != null && absoluteServiceUri.IsAbsoluteUri"); Debug.Assert(batchStream != null, "batchStream != null"); this.absoluteServiceUri = absoluteServiceUri; this.absoluteRequestUri = RequestUriProcessor.GetAbsoluteUriFromReference(batchStream.ContentUri, absoluteServiceUri); this.requestHttpMethod = GetHttpMethodName(batchStream.State); this.requestStream = batchStream.GetContentStream(); this.contentId = contentId; foreach (KeyValuePair <string, string> header in batchStream.ContentHeaders) { this.requestHeaders.Add(header.Key, header.Value); } }
/// <summary> /// Gets the target link value for an <see cref="ODataOperation"/> /// </summary> /// <param name="entityToSerialize">The current entity being serialized.</param> /// <param name="operation">The operation to generate the link for.</param> /// <param name="entityHasMultipleActionsWithSameName">Whether or not there are multiple operations in the current scope with the same name as the current operation.</param> /// <returns>Uri representing link to use for invoking this operation.</returns> internal Uri BuildTargetLink(EntityToSerialize entityToSerialize, OperationWrapper operation, bool entityHasMultipleActionsWithSameName) { Debug.Assert(entityToSerialize != null, "entityToSerialize != null"); Debug.Assert(operation != null, "operation != null"); Debug.Assert(operation.BindingParameter != null, "operation.BindingParameter != null"); Debug.Assert(operation.BindingParameter.ParameterType != null, "operation.BindingParameter.ParameterType != null"); string targetSegment = operation.GetActionTargetSegmentByResourceType(entityToSerialize.ResourceType, this.namespaceName); // If there are multiple operations with the same name, then using the edit link of the entry would cause the target to potentially resolve to the wrong // operation. Instead, use the actual binding type of the specific operation. if (entityHasMultipleActionsWithSameName) { Uri editLinkWithBindingType = RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.AbsoluteEditLinkWithoutSuffix, operation.BindingParameter.ParameterType.FullName); return(RequestUriProcessor.AppendUnescapedSegment(editLinkWithBindingType, targetSegment)); } return(RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.AbsoluteEditLink, targetSegment)); }
private ODataStreamReferenceValue GetNamedStreamPropertyValue(object element, ResourceProperty namedStreamProperty, Uri relativeUri) { string str; Uri uri; string str2; base.Service.StreamProvider.GetStreamDescription(element, namedStreamProperty, base.Service.OperationContext, out str, out uri, out str2); ODataStreamReferenceValue value2 = new ODataStreamReferenceValue { ContentType = str2, EditLink = RequestUriProcessor.AppendUnescapedSegment(relativeUri, namedStreamProperty.Name) }; if (!string.IsNullOrEmpty(str)) { value2.ETag = str; } value2.ReadLink = uri; return(value2); }
internal BatchServiceHost(Uri absoluteServiceUri, IODataRequestMessage operationMessage, string contentId, ODataBatchWriter writer, Version maxDataServiceVersion, Version minDataServiceVersion, Version dataServiceVersion) : this(writer) { this.absoluteServiceUri = absoluteServiceUri; this.absoluteRequestUri = RequestUriProcessor.GetAbsoluteUriFromReference(operationMessage.Url, absoluteServiceUri, dataServiceVersion); this.requestHttpMethod = operationMessage.Method; this.contentId = contentId; foreach (KeyValuePair <string, string> pair in operationMessage.Headers) { this.requestHeaders.Add(pair.Key, pair.Value); } if (string.IsNullOrEmpty(this.requestHeaders["MaxDataServiceVersion"])) { this.requestHeaders["MaxDataServiceVersion"] = maxDataServiceVersion.ToString(); } if (string.IsNullOrEmpty(this.requestHeaders["MinDataServiceVersion"])) { this.requestHeaders["MinDataServiceVersion"] = minDataServiceVersion.ToString(); } this.requestStream = operationMessage.GetStream(); }
public void FilterSpatialMathOperators() { var tests = new[] { new { Operator = "add", ErrorName = "Add" }, new { Operator = "mul", ErrorName = "Multiply" }, }; this.serviceFactory.SetRequestUri("Entities"); foreach (var test in tests) { // property vs spatial literal this.serviceFactory.SetRequestUri("Entities?$filter=Spatial " + test.Operator + " geography'SRID=1234;POINT(10 20)'"); var service = this.serviceFactory.CreateService(); Action processUri = () => RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); processUri.ShouldThrow <DataServiceException>().WithMessage(Microsoft.OData.Core.Strings.MetadataBinder_IncompatibleOperandsError("Edm.Geography", "Edm.GeographyPoint", test.ErrorName)); } }
/// <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); } }
/// <summary> /// Creates the navigation link for the given navigation property. /// </summary> /// <param name="entityToSerialize">Entity that is currently being serialized.</param> /// <param name="navigationProperty">The metadata for the navigation property.</param> /// <returns>The navigation link for the given property.</returns> private ODataNavigationLink GetNavigationLink(EntityToSerialize entityToSerialize, ResourceProperty navigationProperty) { Debug.Assert(entityToSerialize != null, "entityToSerialize != null"); Debug.Assert(navigationProperty != null, "navigationProperty != null"); string navLinkName = navigationProperty.Name; ODataNavigationLink navLink = new ODataNavigationLink { Name = navLinkName, IsCollection = navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference }; // Always pass the relative uri to the ODatalib. For Json, they will convert the relative uri // into absolute uri using the BaseUri property on the ODataWriterSettings. For atom, ODataLib // will write the relative uri. this.PayloadMetadataPropertyManager.SetUrl(navLink, () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.RelativeEditLink, navLinkName)); if (this.Service.Configuration.DataServiceBehavior.IncludeAssociationLinksInResponse) { this.PayloadMetadataPropertyManager.SetAssociationLinkUrl(navLink, () => GetAssociationLinkUrl(entityToSerialize, navigationProperty)); } return(navLink); }
private void WriteNavigationProperties(IExpandedResult expanded, EntityToSerialize entityToSerialize, bool resourceInstanceInFeed, IEnumerable <ProjectionNode> projectionNodesForCurrentResourceType) { Debug.Assert(entityToSerialize != null, "entityToSerialize != null"); Debug.Assert( projectionNodesForCurrentResourceType == null || projectionNodesForCurrentResourceType.All(projectionNode => projectionNode.TargetResourceType.IsAssignableFrom(entityToSerialize.ResourceType)), "The projection nodes must be filtered to the current resource type only."); IEnumerable <ResourceProperty> navProperties = projectionNodesForCurrentResourceType == null ? this.Provider.GetResourceSerializableProperties(this.CurrentContainer, entityToSerialize.ResourceType).Where(p => p.TypeKind == ResourceTypeKind.EntityType) : projectionNodesForCurrentResourceType.Where(p => p.Property != null && p.Property.TypeKind == ResourceTypeKind.EntityType).Select(p1 => p1.Property); foreach (ResourceProperty property in navProperties) { ResourcePropertyInfo navProperty = this.GetNavigationPropertyInfo(expanded, entityToSerialize.Entity, entityToSerialize.ResourceType, property); ODataNavigationLink navLink = this.GetNavigationLink(entityToSerialize, navProperty.Property); // WCF Data Services show performance degradation with JsonLight when entities have > 25 Navgations on writing entries // DEVNOTE: for performance reasons, if the link has no content due to the metadata level, and is not expanded // then don't tell ODataLib about it at all. if (navLink.Url == null && navLink.AssociationLinkUrl == null && !navProperty.Expand) { continue; } var linkArgs = new DataServiceODataWriterNavigationLinkArgs(navLink, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(linkArgs); if (navProperty.Expand) { object navPropertyValue = navProperty.Value; IExpandedResult navPropertyExpandedResult = navPropertyValue as IExpandedResult; object expandedPropertyValue = navPropertyExpandedResult != null? GetExpandedElement(navPropertyExpandedResult) : navPropertyValue; bool needPop = this.PushSegmentForProperty(navProperty.Property, entityToSerialize.ResourceType, navProperty.ExpandedNode); // if this.CurrentContainer is null, the target set of the navigation property is hidden. if (this.CurrentContainer != null) { if (navProperty.Property.Kind == ResourcePropertyKind.ResourceSetReference) { IEnumerable enumerable; bool collection = WebUtil.IsElementIEnumerable(expandedPropertyValue, out enumerable); Debug.Assert(collection, "metadata loading must have ensured that navigation set properties must implement IEnumerable"); QueryResultInfo queryResults = new QueryResultInfo(enumerable); try { queryResults.MoveNext(); Func <Uri> getNavPropertyRelativeUri = () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.RelativeEditLink, navLink.Name); Func <Uri> getNavPropertyAbsoluteUri = () => RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.AbsoluteEditLink, navLink.Name); this.WriteFeedElements(navPropertyExpandedResult, queryResults, navProperty.Property.ResourceType, navLink.Name, getNavPropertyRelativeUri, getNavPropertyAbsoluteUri, false); } finally { // After the navigation property is completely serialized, dispose the property value. WebUtil.Dispose(queryResults); } } else if (WebUtil.IsNullValue(expandedPropertyValue)) { // Write a null reference navigation property var entryArgs = new DataServiceODataWriterEntryArgs(null, null, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(entryArgs); this.dataServicesODataWriter.WriteEnd(entryArgs); } else { this.WriteEntry(navPropertyExpandedResult, expandedPropertyValue, resourceInstanceInFeed, navProperty.Property.ResourceType); } } this.PopSegmentName(needPop); } this.dataServicesODataWriter.WriteEnd(linkArgs); // end of navigation property } }
/// <summary> /// Gets the association link URL. /// </summary> /// <param name="entityToSerialize">The entity to serialize.</param> /// <param name="navigationProperty">The navigation property.</param> /// <returns>The association link url.</returns> private static Uri GetAssociationLinkUrl(EntityToSerialize entityToSerialize, ResourceProperty navigationProperty) { Uri associationLinkUri = RequestUriProcessor.AppendUnescapedSegment(entityToSerialize.SerializedKey.RelativeEditLink, navigationProperty.Name); return(RequestUriProcessor.AppendEscapedSegment(associationLinkUri, XmlConstants.UriLinkSegment)); }
/// <summary> /// Wraps a lazy URI with another that will have the given string appended if it is not null. /// </summary> /// <param name="lazyUri">The lazy URI to wrap.</param> /// <param name="suffix">The suffix for the URI.</param> /// <returns>A new lazy URI which will have the suffix, or the same instance if the suffix was null.</returns> private static SimpleLazy <Uri> AppendLazilyIfNeeded(SimpleLazy <Uri> lazyUri, string suffix) { return(suffix == null ? lazyUri : new SimpleLazy <Uri>(() => RequestUriProcessor.AppendUnescapedSegment(lazyUri.Value, suffix), false)); }