/// <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);
        }