Esempio n. 1
0
        /// <summary>
        /// Translates resource bound expression tree to a URI.
        /// </summary>
        /// <param name='context'>Data context used to generate type names for types.</param>
        /// <param name="addTrailingParens">flag to indicate whether generated URI should include () if leaf is ResourceSet</param>
        /// <param name="e">The expression to translate</param>
        /// <param name="uri">uri</param>
        /// <param name="version">version for query</param>
        internal static void Translate(DataServiceContext context, bool addTrailingParens, Expression e, out Uri uri, out Version version)
        {
            var writer = new UriWriter(context);

            writer.Visit(e);
            string fullUri = writer.uriBuilder.ToString();

            if (writer.alias.Any())
            {
                if (fullUri.IndexOf(UriHelper.QUESTIONMARK) > -1)
                {
                    fullUri += UriHelper.AMPERSAND;
                }
                else
                {
                    fullUri += UriHelper.QUESTIONMARK;
                }

                foreach (var kv in writer.alias)
                {
                    fullUri += kv.Key;
                    fullUri += UriHelper.EQUALSSIGN;
                    fullUri += kv.Value;
                    fullUri += UriHelper.AMPERSAND;
                }

                fullUri = fullUri.Substring(0, fullUri.Length - 1);
            }


            uri     = UriUtil.CreateUri(fullUri, UriKind.Absolute);
            version = writer.uriVersion;
        }
        /// <summary>Loads the collection asynchronously by loading the results from the request Uri.</summary>
        /// <param name="requestUri">The request uri to download results from.</param>
        /// <remarks>This method uses the event-based async pattern.
        /// The method returns immediately without waiting for the query to complete. Then it calls the handler of the
        /// <see cref="LoadCompleted"/> event exactly once on the UI thread. The event will be raised regradless
        /// if the query succeeded or not.
        /// This class only support one asynchronous operation in flight.</remarks>
        public void LoadAsync(Uri requestUri)
        {
            Util.CheckArgumentNull(requestUri, "requestUri");

            if (!this.IsTracking)
            {
                throw new InvalidOperationException(Strings.DataServiceCollection_OperationForTrackedOnly);
            }

            if (this.ongoingAsyncOperation != null)
            {
                throw new InvalidOperationException(Strings.DataServiceCollection_MultipleLoadAsyncOperationsAtTheSameTime);
            }

            DataServiceContext context = this.observer.Context;

            requestUri = UriUtil.CreateUri(context.BaseUri, requestUri);

            this.BeginLoadAsyncOperation(
                asyncCallback => context.BeginExecute <T>(requestUri, asyncCallback, null),
                asyncResult =>
            {
                QueryOperationResponse <T> response = (QueryOperationResponse <T>)context.EndExecute <T>(asyncResult);
                this.Load(response);
                return(response);
            });
        }
        /// <summary>uri to edit the entity</summary>
        /// <param name="baseUriResolver">retrieves the baseUri to use for a given entity set.</param>
        /// <param name="queryLink">whether to return the query link or edit link</param>
        /// <returns>absolute uri which can be used to edit the entity</returns>
        internal Uri GetResourceUri(UriResolver baseUriResolver, bool queryLink)
        {
            // If the entity was inserted using the AddRelatedObject API
            if (this.ParentEntityDescriptor != null)
            {
                // This is the batch scenario, where the entity might not have been saved yet, and there is another operation
                // (for e.g. PUT $1/links/BestFriend or something). Hence we need to generate a Uri with the changeorder number.
                if (this.ParentEntityDescriptor.Identity == null)
                {
                    Uri relativeReferenceUri = UriUtil.CreateUri("$" + this.ParentEntityDescriptor.ChangeOrder.ToString(CultureInfo.InvariantCulture), UriKind.Relative);
                    Uri absoluteReferenceUri = baseUriResolver.GetOrCreateAbsoluteUri(relativeReferenceUri);
                    Uri requestUri           = UriUtil.CreateUri(this.ParentProperty, UriKind.Relative);
                    return(UriUtil.CreateUri(absoluteReferenceUri, requestUri));
                }
                else
                {
                    Debug.Assert(this.ParentEntityDescriptor.ParentEntityDescriptor == null, "This code assumes that parentChild relationships will only ever be one level deep");
                    Debug.Assert(this.ParentProperty != null, "ParentProperty != null");
                    LinkInfo linkInfo;
                    if (this.ParentEntityDescriptor.TryGetLinkInfo(this.ParentProperty, out linkInfo))
                    {
                        if (linkInfo.NavigationLink != null)
                        {
                            return(linkInfo.NavigationLink);
                        }
                    }

                    return(UriUtil.CreateUri(this.ParentEntityDescriptor.GetLink(queryLink), this.GetLink(queryLink)));
                }
            }
            else
            {
                return(this.GetLink(queryLink));
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Translates resource bound expression tree to a URI.
 /// </summary>
 /// <param name='context'>Data context used to generate type names for types.</param>
 /// <param name="addTrailingParens">flag to indicate whether generated URI should include () if leaf is ResourceSet</param>
 /// <param name="e">The expression to translate</param>
 /// <param name="uri">uri</param>
 /// <param name="version">version for query</param>    
 internal static void Translate(DataServiceContext context, bool addTrailingParens, Expression e, out Uri uri, out Version version)
 {
     var writer = new UriWriter(context);
     writer.leafResource = addTrailingParens ? (e as QueryableResourceExpression) : null;
     writer.Visit(e);
     uri = UriUtil.CreateUri(writer.uriBuilder.ToString(), UriKind.Absolute);
     version = writer.uriVersion;
 }
Esempio n. 5
0
        /// <summary>
        /// If necessary will create an absolute uri by combining the BaseUri and requestUri
        /// </summary>
        /// <param name="requestUri">The uri specified by the user</param>
        /// <returns>An absolute Uri based on the requestUri and if nessesary the BaseUri</returns>
        internal Uri GetOrCreateAbsoluteUri(Uri requestUri)
        {
            Util.CheckArgumentNull(requestUri, "requestUri");
            if (!requestUri.IsAbsoluteUri)
            {
                return(UriUtil.CreateUri(this.GetBaseUriWithSlash(() => Strings.Context_RequestUriIsRelativeBaseUriRequired), requestUri));
            }

            return(requestUri);
        }
Esempio n. 6
0
        /// <summary>
        /// Creates a ODataRequestMessage for batch request.
        /// </summary>
        /// <returns>Returns an instance of ODataRequestMessage for the batch request.</returns>
        private ODataRequestMessageWrapper CreateBatchRequest()
        {
            Uri requestUri           = UriUtil.CreateUri(this.RequestInfo.BaseUriResolver.GetBaseUriWithSlash(), UriUtil.CreateUri("$batch", UriKind.Relative));
            HeaderCollection headers = new HeaderCollection();

            headers.SetRequestVersion(Util.ODataVersion4, this.RequestInfo.MaxProtocolVersionAsVersion);
            headers.SetHeader(XmlConstants.HttpContentType, CreateMultiPartMimeContentType());
            this.RequestInfo.Format.SetRequestAcceptHeaderForBatch(headers);

            return(this.CreateTopLevelRequest(XmlConstants.HttpMethodPost, requestUri, headers, this.RequestInfo.HttpStack, null /*descriptor*/));
        }
Esempio n. 7
0
            /// <summary>
            /// Appends to create the entity instance URI for the specified <paramref name="entityInstance"/>.
            /// </summary>
            /// <param name="baseUri">The URI to append to</param>
            /// <param name="entityInstance">The entity instance to use.</param>
            /// <returns>
            /// The entity instance URI.
            /// </returns>
            internal override Uri BuildEntityInstanceUri(Uri baseUri, IEdmStructuredValue entityInstance)
            {
                var builder = new StringBuilder();

                if (baseUri != null)
                {
                    builder.Append(UriUtil.UriToString(baseUri));
                }

                this.conventions.AppendKeyExpression(entityInstance, builder);
                return(UriUtil.CreateUri(builder.ToString(), UriKind.RelativeOrAbsolute));
            }
Esempio n. 8
0
        /// <summary>
        /// Validates the value of the 'Location' response header.
        /// </summary>
        /// <param name="location">the value as seen on the wire.</param>
        /// <returns>an absolute Uri</returns>
        internal static Uri ValidateLocationHeader(string location)
        {
            // We used to call the Uri constructor with the kind set to Absolute.
            // Hence now checking for the absoluteness.
            Uri locationUri = UriUtil.CreateUri(location, UriKind.RelativeOrAbsolute);
            if (!locationUri.IsAbsoluteUri)
            {
                throw Error.InvalidOperation(Strings.Context_LocationHeaderExpectsAbsoluteUri);
            }

            return locationUri;
        }
Esempio n. 9
0
        /// <summary>
        /// Returns a slash terminated Uri.
        ///
        /// Will be the passed in one if it is already slash terminated, or a new one
        /// if the passed in one is not slash terminated.
        /// </summary>
        /// <param name="uri">The Uri to be slash terminated</param>
        /// <returns>A slash terminated version of the passed in Uri.</returns>
        private static Uri ForceSlashTerminatedUri(Uri uri)
        {
            Debug.Assert(uri.IsAbsoluteUri, "the uri must be an absolute uri");
            Debug.Assert(String.IsNullOrEmpty(uri.Query), "the uri must not have any query");
            Debug.Assert(String.IsNullOrEmpty(uri.Fragment), "the uri must not have any fragment");

            string uriString = UriUtil.UriToString(uri);

            if (uriString[uriString.Length - 1] != '/')
            {
                return(UriUtil.CreateUri(uriString + "/", UriKind.Absolute));
            }

            return(uri);
        }
Esempio n. 10
0
        /// <summary>base uri with no trailing slash</summary>
        /// <param name="entitySetName">the name of the entitSet whose Uri will be retrieved.</param>
        /// <returns>the baseUri ended with a slash for the entitySetName passed in.</returns>
        internal Uri GetEntitySetUri(string entitySetName)
        {
            Uri resolved = this.GetEntitySetUriFromResolver(entitySetName);

            if (resolved != null)
            {
                return(ForceNonSlashTerminatedUri(resolved));
            }

            if (this.baseUriWithSlash != null)
            {
                return(UriUtil.CreateUri(this.baseUriWithSlash, UriUtil.CreateUri(entitySetName, UriKind.Relative)));
            }

            throw Error.InvalidOperation(Strings.Context_ResolveEntitySetOrBaseUriRequired(entitySetName));
        }
Esempio n. 11
0
        /// <summary>
        /// Validates the value of the identity, the atom:id or OData-EntityId
        /// </summary>
        /// <param name="identityValue">The value to validate</param>
        /// <returns>an absolute Uri</returns>
        internal static Uri ValidateIdentityValue(string identityValue)
        {
            Uri identity;

            try
            {
                // here we could just assign idText to Identity
                // however we used to check for AbsoluteUri, thus we need to
                // convert string to Uri and check for absoluteness
                identity = UriUtil.CreateUri(identityValue, UriKind.Absolute);
            }
            catch (FormatException)
            {
                throw Error.InvalidOperation(Strings.Context_TrackingExpectsAbsoluteUri);
            }

            return(identity);
        }
        /// <summary>
        /// Try and get the navigation link. If the navigation link is not specified, then its used the self link of the entity and
        /// appends the property name.
        /// </summary>
        /// <param name="baseUriResolver">retrieves the appropriate baseUri for a given entitySet.</param>
        /// <param name="property">ClientProperty instance representing the navigation property.</param>
        /// <returns>returns the uri for the given link. If the link is not present, its uses the self link of the current entity and appends the navigation property name.</returns>
        internal Uri GetNavigationLink(UriResolver baseUriResolver, ClientPropertyAnnotation property)
        {
            LinkInfo linkInfo = null;
            Uri      uri      = null;

            if (this.TryGetLinkInfo(property.PropertyName, out linkInfo))
            {
                uri = linkInfo.NavigationLink;
            }

            if (uri == null)
            {
                Uri relativeUri = UriUtil.CreateUri(property.PropertyName, UriKind.Relative);
                uri = UriUtil.CreateUri(this.GetResourceUri(baseUriResolver, true /*queryLink*/), relativeUri);
            }

            return(uri);
        }
Esempio n. 13
0
        /// <summary>
        /// Writes an entity reference link.
        /// </summary>
        /// <param name="binding">The link descriptor.</param>
        /// <param name="requestMessage">The request message used for writing the payload.</param>
        internal void WriteEntityReferenceLink(LinkDescriptor binding, ODataRequestMessageWrapper requestMessage)
#endif
        {
            using (ODataMessageWriter messageWriter = Serializer.CreateMessageWriter(requestMessage, this.requestInfo, false /*isParameterPayload*/))
            {
                EntityDescriptor targetResource = this.requestInfo.EntityTracker.GetEntityDescriptor(binding.Target);

                Uri targetReferenceLink = targetResource.GetLatestIdentity();

                if (targetReferenceLink == null)
                {
#if DEBUG
                    Debug.Assert(isBatch, "we should be cross-referencing entities only in batch scenarios");
#endif
                    targetReferenceLink = UriUtil.CreateUri("$" + targetResource.ChangeOrder.ToString(CultureInfo.InvariantCulture), UriKind.Relative);
                }

                ODataEntityReferenceLink referenceLink = new ODataEntityReferenceLink();
                referenceLink.Url = targetReferenceLink;
                messageWriter.WriteEntityReferenceLink(referenceLink);
            }
        }
        /// <summary>
        /// In V1, we used to not support self links. Hence we used to use edit links as self links.
        /// IN V2, we are adding support for self links. But if there are not specified, we need to
        /// fall back on the edit link.
        /// </summary>
        /// <param name="queryLink">whether to get query link or the edit link.</param>
        /// <returns>the query or the edit link, as specified in the <paramref name="queryLink"/> parameter.</returns>
        private Uri GetLink(bool queryLink)
        {
            // If asked for a self link and self-link is present, return self link
            Uri link;

            if (queryLink && this.SelfLink != null)
            {
                return(this.SelfLink);
            }

            // otherwise return edit link if present.
            if ((link = this.GetLatestEditLink()) != null)
            {
                return(link);
            }

            if (this.State != EntityStates.Added)
            {
                throw new ArgumentNullException(Strings.EntityDescriptor_MissingSelfEditLink(this.identity));
            }
            else
            {
                Debug.Assert(this.TransientEntityDescriptor == null, "The transient entity container must be null, when the entity is in added state");

                // If the entity is in added state, and either the parent property or the addToUri must be non-null
                Debug.Assert(this.addToUri != null || !String.IsNullOrEmpty(this.ParentPropertyForInsert), "For entities in added state, parentProperty or addToUri must be specified");
                if (this.addToUri != null)
                {
                    return(this.addToUri);
                }
                else
                {
                    return(UriUtil.CreateUri(this.ParentPropertyForInsert, UriKind.Relative));
                }
            }
        }
Esempio n. 15
0
 /// <summary>
 /// Create an instance of primitive type from a string representation
 /// </summary>
 /// <param name="text">The string representation</param>
 /// <returns>An instance of primitive type</returns>
 internal override object Parse(String text)
 {
     return(UriUtil.CreateUri(text, UriKind.RelativeOrAbsolute));
 }