/// <summary> /// Accept a V3 request URI and return a V4 request URI. V4 request URI retains base path. /// </summary> /// <param name="requestUri">V3 Request URI</param> /// <returns>V4 Request URI</returns> public Uri TranslateUri(Uri requestUri) { // Use UriTranslator to walk v3 segments, translating each to v4 and returning. ODataPath v3path = new ODataUriParser(this.v3Model, this.serviceRoot).ParsePath(requestUri); UriSegmentTranslator uriTranslator = new UriSegmentTranslator(this.v4Model); Microsoft.OData.UriParser.ODataPath v4path = new Microsoft.OData.UriParser.ODataPath(v3path.WalkWith(uriTranslator)); // Parse query options for translation NameValueCollection requestQuery = HttpUtility.ParseQueryString(requestUri.Query); // Create a v4 ODataUri and utilized ODataUriExtensions methods to build v4 URI Microsoft.OData.ODataUri v4Uri = new Microsoft.OData.ODataUri() { Path = v4path, Filter = ParseFilterFromQueryOrNull(requestQuery, v4path, v3path) }; Uri v4RelativeUri = Microsoft.OData.ODataUriExtensions.BuildUri(v4Uri, Microsoft.OData.ODataUrlKeyDelimiter.Parentheses); Uri v4FullUri = new Uri(serviceRoot, v4RelativeUri); // Translated query only contains translated filter clause // We need to move everything from v3 query that does not require translation to v4 query NameValueCollection translatedQuery = HttpUtility.ParseQueryString(v4FullUri.Query); // Copy values from requestQuery to new translated query. Iterate with multiple loops // because NameValueCollections also support multiple values to one key foreach (string k in requestQuery) { foreach (string v in requestQuery.GetValues(k)) { string key = k.Trim(); if (key == "$inlinecount") { translatedQuery["$count"] = ParseInlineCountFromQuery(v.Trim()); } else if (key != "$filter") { translatedQuery[k] = v; } } } UriBuilder builder = new UriBuilder(serviceRoot.Scheme, serviceRoot.Host, serviceRoot.Port, v4FullUri.AbsolutePath); // NameValueCollection ToString is overriden to produce a URL-encoded string, decode it to maintain consistency builder.Query = WebUtility.UrlDecode(translatedQuery.ToString()); return(builder.Uri); }