diff --git a/src/Microsoft.OData.Core/ODataContextUrlInfo.cs b/src/Microsoft.OData.Core/ODataContextUrlInfo.cs
index 6ec3b7170c..86cc7b85cc 100644
--- a/src/Microsoft.OData.Core/ODataContextUrlInfo.cs
+++ b/src/Microsoft.OData.Core/ODataContextUrlInfo.cs
@@ -297,7 +297,7 @@ private static string ComputeNavigationPath(EdmNavigationSourceKind kind, ODataU
             string navigationPath = null;
             if (kind == EdmNavigationSourceKind.ContainedEntitySet && odataUri != null && odataUri.Path != null)
             {
-                ODataPath odataPath = odataUri.Path.TrimEndingTypeSegment().TrimEndingKeySegment();
+                ODataPath odataPath = odataUri.Path.TrimEndingTypeAndKeySegments();
                 if (!(odataPath.LastSegment is NavigationPropertySegment) && !(odataPath.LastSegment is OperationSegment))
                 {
                     throw new ODataException(Strings.ODataContextUriBuilder_ODataPathInvalidForContainedElement(odataPath.ToContextUrlPathString()));
@@ -322,15 +322,13 @@ private static string ComputeNavigationPath(EdmNavigationSourceKind kind, in ODa
             string navigationPath = null;
             if (kind == EdmNavigationSourceKind.ContainedEntitySet && odataUri.Path != null)
             {
-                ODataPath odataPath = odataUri.Path.TrimEndingTypeSegment().TrimEndingKeySegment();
+                ODataPath odataPath = odataUri.Path.TrimEndingTypeAndKeySegments();
                 if (!(odataPath.LastSegment is NavigationPropertySegment) && !(odataPath.LastSegment is OperationSegment))
                 {
                     throw new ODataException(Strings.ODataContextUriBuilder_ODataPathInvalidForContainedElement(odataPath.ToContextUrlPathString()));
                 }
-
                 navigationPath = odataPath.ToContextUrlPathString();
             }
-
             return navigationPath ?? navigationSource;
         }
 
diff --git a/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt
index e69de29bb2..103f295f00 100644
--- a/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static Microsoft.OData.UriParser.ODataPathExtensions.TrimEndingTypeAndKeySegments(this Microsoft.OData.UriParser.ODataPath path) -> Microsoft.OData.UriParser.ODataPath
\ No newline at end of file
diff --git a/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt
index e69de29bb2..103f295f00 100644
--- a/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static Microsoft.OData.UriParser.ODataPathExtensions.TrimEndingTypeAndKeySegments(this Microsoft.OData.UriParser.ODataPath path) -> Microsoft.OData.UriParser.ODataPath
\ No newline at end of file
diff --git a/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt
index e69de29bb2..103f295f00 100644
--- a/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static Microsoft.OData.UriParser.ODataPathExtensions.TrimEndingTypeAndKeySegments(this Microsoft.OData.UriParser.ODataPath path) -> Microsoft.OData.UriParser.ODataPath
\ No newline at end of file
diff --git a/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
index e69de29bb2..103f295f00 100644
--- a/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
@@ -0,0 +1 @@
+static Microsoft.OData.UriParser.ODataPathExtensions.TrimEndingTypeAndKeySegments(this Microsoft.OData.UriParser.ODataPath path) -> Microsoft.OData.UriParser.ODataPath
\ No newline at end of file
diff --git a/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathExtensions.cs b/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathExtensions.cs
index 87b4fa1bbc..f0d02cd1c5 100644
--- a/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathExtensions.cs
+++ b/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathExtensions.cs
@@ -137,6 +137,22 @@ public static ODataPath TrimEndingTypeSegment(this ODataPath path)
             return handler.FirstPart;
         }
 
+        /// <summary>
+        /// Creates a <see cref="ODataPath"/> that is <paramref name="path"/> with the type segments and key segments removed from the end
+        /// </summary>
+        /// <param name="path">The <see cref="ODataPath"/> to trim the ending of</param>
+        /// <returns>A <see cref="ODataPath"/> without type-cast and key segments at the end</returns>
+        /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="path"/> is <see langword="null"/></exception>
+        public static ODataPath TrimEndingTypeAndKeySegments(this ODataPath path)
+        {
+            if (path == null)
+            {
+                throw Error.ArgumentNull(nameof(path));
+            }
+
+            return new ODataPath(path.Segments.Take(path.Segments.FindLastIndex(segment => !(segment is KeySegment || segment is TypeSegment)) + 1));
+        }
+
         /// <summary>
         /// Creates a new ODataPath with the specified segment added.
         /// </summary>
diff --git a/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt
index 5f282702bb..9271da2b65 100644
--- a/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt
@@ -1 +1,2 @@
-
\ No newline at end of file
+static System.Collections.Generic.ReadOnlyListExtensions.FindLastIndex<T>(this System.Collections.Generic.IReadOnlyList<T> list, System.Func<T, bool> predicate) -> int
+System.Collections.Generic.ReadOnlyListExtensions
\ No newline at end of file
diff --git a/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt
index 5f282702bb..9271da2b65 100644
--- a/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt
@@ -1 +1,2 @@
-
\ No newline at end of file
+static System.Collections.Generic.ReadOnlyListExtensions.FindLastIndex<T>(this System.Collections.Generic.IReadOnlyList<T> list, System.Func<T, bool> predicate) -> int
+System.Collections.Generic.ReadOnlyListExtensions
\ No newline at end of file
diff --git a/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
index 5f282702bb..9271da2b65 100644
--- a/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
@@ -1 +1,2 @@
-
\ No newline at end of file
+static System.Collections.Generic.ReadOnlyListExtensions.FindLastIndex<T>(this System.Collections.Generic.IReadOnlyList<T> list, System.Func<T, bool> predicate) -> int
+System.Collections.Generic.ReadOnlyListExtensions
\ No newline at end of file
diff --git a/src/Microsoft.OData.Edm/System/Collections/Generic/ReadOnlyListExtensions.cs b/src/Microsoft.OData.Edm/System/Collections/Generic/ReadOnlyListExtensions.cs
new file mode 100644
index 0000000000..c1aafd4aeb
--- /dev/null
+++ b/src/Microsoft.OData.Edm/System/Collections/Generic/ReadOnlyListExtensions.cs
@@ -0,0 +1,45 @@
+namespace System.Collections.Generic
+{
+    /// <summary>
+    /// Extensions methods <see cref="IReadOnlyList{T}"/>
+    /// </summary>
+    public static class ReadOnlyListExtensions
+    {
+        /// <summary>
+        /// Searches for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the last occurrence within the
+        /// entire <see cref="IReadOnlyList{T}"/>
+        /// </summary>
+        /// <typeparam name="T">The type of the elements in <paramref name="list"/></typeparam>
+        /// <param name="list">The <see cref="IReadOnlyList{T}"/> to find the index of the last element of</param>
+        /// <param name="predicate">The <see cref="Func{T, TResult}"/> delegate that defines the conditions of the element to search for.</param>
+        /// <returns>
+        /// The zero-based index of the last occurrence of an element that matches the conditions defined by <paramref name="predicate"/>, if found; otherwise, -1
+        /// </returns>
+        /// <exception cref="ArgumentNullException">Thrown if <paramref name="list"/> or <paramref name="predicate"/> is <see langword="null"/></exception>
+        /// <remarks>
+        /// Copied from <see href="https://github.com/dotnet/runtime/blob/87c25589bda5a79baf8d056501663b8525f366a8/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs#L560"/>
+        /// </remarks>
+        public static int FindLastIndex<T>(this IReadOnlyList<T> list, Func<T, bool> predicate)
+        {
+            if (list == null)
+            {
+                throw new ArgumentNullException(nameof(list));
+            }
+
+            if (predicate == null)
+            {
+                throw new ArgumentNullException(nameof(predicate));
+            }
+
+            for (int i = list.Count - 1; i > -1; --i)
+            {
+                if (predicate(list[i]))
+                {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+    }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/GenerateContextUrlFromSlimUriWithDerivedTypeCastAndKeySegment.xml b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/GenerateContextUrlFromSlimUriWithDerivedTypeCastAndKeySegment.xml
new file mode 100644
index 0000000000..94745422cd
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/GenerateContextUrlFromSlimUriWithDerivedTypeCastAndKeySegment.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" xmlns:ags="http://aggregator.microsoft.com/internal" xmlns:odata="http://schemas.microsoft.com/oDataCapabilities">
+  <edmx:DataServices>
+    <Schema Namespace="ns" Alias="self" xmlns="http://docs.oasis-open.org/odata/ns/edm" xmlns:ags="http://aggregator.microsoft.com/internal" xmlns:odata="http://schemas.microsoft.com/oDataCapabilities">
+      <EntityContainer Name="Container">
+        <EntitySet Name="orders" EntityType="self.order" />
+        <EntitySet Name="categories" EntityType="self.category" />
+      </EntityContainer>
+      <EntityType Name="order">
+        <Key>
+          <PropertyRef Name="id" />
+        </Key>
+        <Property Name="id" Type="Edm.String" Nullable="false" />
+        <NavigationProperty Name="products" Type="Collection(self.product)" ContainsTarget="true" Nullable="false" />
+      </EntityType>
+      <EntityType Name="product">
+        <Key>
+          <PropertyRef Name="id" />
+        </Key>
+        <Property Name="id" Type="Edm.String" Nullable="false" />
+        <Property Name="name" Type="Edm.String" Nullable="false" />
+      </EntityType>
+      <EntityType Name="category">
+        <Key>
+          <PropertyRef Name="id" />
+        </Key>
+        <Property Name="id" Type="Edm.String" Nullable="false" />
+        <Property Name="foo" Type="Edm.String" Nullable="false" />
+      </EntityType>
+      <EntityType Name="derivedProduct" BaseType="self.product">
+        <NavigationProperty Name="category" Type="self.category" ContainsTarget="true" />
+      </EntityType>
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightWriterTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightWriterTests.cs
index d07e797efd..9dc9ccc998 100644
--- a/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightWriterTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/ODataJsonLightWriterTests.cs
@@ -8,11 +8,18 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.IO;
+using System.Linq;
+using System.Reflection;
 using System.Text;
 using System.Threading.Tasks;
+using System.Xml;
 using Microsoft.OData.Edm;
+using Microsoft.OData.Edm.Csdl;
+#if NETCOREAPP3_1_OR_GREATER
 using Microsoft.OData.Json;
+#endif
 using Microsoft.OData.JsonLight;
+using Microsoft.OData.UriParser;
 using Microsoft.OData.Tests;
 using Microsoft.Test.OData.DependencyInjection;
 using Xunit;
@@ -739,6 +746,181 @@ public async Task WriteEntityReferenceLinkAsync()
                 result);
         }
 
+        /// <summary>
+        /// Gets the name of the caller method of this method
+        /// </summary>
+        /// <param name="caller">The string that the method name of the caller will be written into</param>
+        /// <returns>The name of the caller method of this method</returns>
+        public static string GetCurrentMethodName([System.Runtime.CompilerServices.CallerMemberName] string caller = null)
+        {
+            return caller;
+        }
+
+        /// <summary>
+        /// A <see cref="IEdmNavigationSource"/> that pretends to be the "products" contained navigation collection for the purposes of computing a context URL
+        /// </summary>
+        private sealed class MockNavigationSource : IEdmNavigationSource, IEdmContainedEntitySet, IEdmUnknownEntitySet
+        {
+            public IEnumerable<IEdmNavigationPropertyBinding> NavigationPropertyBindings => throw new NotImplementedException();
+
+            public IEdmPathExpression Path => throw new NotImplementedException();
+
+            public IEdmType Type => new EdmEntityType("ns", "products");
+
+            public string Name => "products";
+
+            public IEdmNavigationSource ParentNavigationSource => throw new NotImplementedException();
+
+            public IEdmNavigationProperty NavigationProperty => throw new NotImplementedException();
+
+            public IEnumerable<IEdmNavigationPropertyBinding> FindNavigationPropertyBindings(IEdmNavigationProperty navigationProperty)
+            {
+                throw new NotImplementedException();
+            }
+
+            public IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty)
+            {
+                throw new NotImplementedException();
+            }
+
+            public IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty, IEdmPathExpression bindingPath)
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+#if !NETCOREAPP1_1
+        /// <summary>
+        /// Generates a context URL from a <see cref="ODataUriSlim"/> that ends with cast and key segments
+        /// </summary>
+        /// <returns><see cref="void"/></returns>
+        [Fact]
+        public static void GenerateContextUrlFromSlimUriWithDerivedTypeCastAndKeySegment()
+        {
+            var domain = new Uri("http://tempuri.org");
+            var requestUrl = new Uri(domain, "/orders('1')/products/ns.derivedProduct('2')");
+
+            // load the CSDL from the embedded resources
+            var assembly = Assembly.GetExecutingAssembly();
+            var currentMethod = GetCurrentMethodName();
+            var csdlResourceName = assembly.GetManifestResourceNames().Where(name => name.EndsWith($"{currentMethod}.xml")).Single();
+
+            // parse the CSDL
+            IEdmModel model;
+            using (var csdlResourceStream = assembly.GetManifestResourceStream(csdlResourceName))
+            {
+                using (var xmlReader = XmlReader.Create(csdlResourceStream))
+                {
+                    if (!CsdlReader.TryParse(xmlReader, out model, out var errors))
+                    {
+                        Assert.True(false, string.Join(Environment.NewLine, errors));
+                    }
+                }
+            }
+
+            var uriParser = new ODataUriParser(model, domain, requestUrl);
+            var slimUri = new ODataUriSlim(uriParser.ParseUri());
+            var contextUrlInfo = ODataContextUrlInfo.Create(new MockNavigationSource(), "ns.product", true, slimUri, ODataVersion.V4);
+            Assert.Equal(@"orders('1')/products", contextUrlInfo.NavigationPath);
+        }
+
+        /// <summary>
+        /// Writes a resource as the response to a request where the URL ends with a combined cast and key segment
+        /// </summary>
+        /// <returns><see cref="void"/></returns>
+        [Fact]
+        public static async Task WriteContextWithDerivedTypeCastAndKeySegmentAsync()
+        {
+            var domain = new Uri("http://tempuri.org");
+            var requestUrl = new Uri(domain, "/orders('1')/products/ns.derivedProduct('2')");
+            var serviceSideResponseResource = new ODataResource
+            {
+                TypeName = "ns.product",
+                Properties = new List<ODataProperty>
+                {
+                    new ODataProperty
+                    {
+                        Name = "id",
+                        Value = "1",
+                        SerializationInfo = new ODataPropertySerializationInfo
+                        {
+                            PropertyKind = ODataPropertyKind.Key
+                        },
+                    },
+                    new ODataProperty
+                    {
+                        Name = "name",
+                        Value = "somename",
+                    },
+                },
+            };
+            var expectedResponsePayload = 
+                "{" +
+                    "\"@odata.context\":\"http://tempuri.org/$metadata#orders('1')/products/$entity\"," +
+                    "\"id\":\"1\"," +
+                    "\"name\":\"somename\"" + 
+                "}";
+
+            // load the CSDL from the embedded resources
+            var assembly = Assembly.GetExecutingAssembly();
+            var currentMethod = GetCurrentMethodName();
+            var csdlResourceName = assembly.GetManifestResourceNames().Where(name => name.EndsWith($"{currentMethod}.xml")).Single();
+
+            // parse the CSDL
+            IEdmModel model;
+            using (var csdlResourceStream = assembly.GetManifestResourceStream(csdlResourceName))
+            {
+                using (var xmlReader = XmlReader.Create(csdlResourceStream))
+                {
+                    if (!CsdlReader.TryParse(xmlReader, out model, out var errors))
+                    {
+                        Assert.True(false, string.Join(Environment.NewLine, errors));
+                    }
+                }
+            }
+
+            using (var memoryStream = new MemoryStream())
+            {
+                // initialize the json response writer
+                var uriParser = new ODataUriParser(model, domain, requestUrl);
+                var odataMessageWriterSettings = new ODataMessageWriterSettings
+                {
+                    EnableMessageStreamDisposal = false,
+                    Version = ODataVersion.V4,
+                    ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*"),
+                    ODataUri = uriParser.ParseUri(),
+                };
+                var messageInfo = new ODataMessageInfo
+                {
+                    MessageStream = memoryStream,
+                    MediaType = new ODataMediaType("application", "json"),
+                    Encoding = Encoding.Default,
+                    IsResponse = true,
+                    IsAsync = true,
+                    Model = model,
+                };
+                var jsonLightOutputContext = new ODataJsonLightOutputContext(messageInfo, odataMessageWriterSettings);
+                var jsonLightWriter = new ODataJsonLightWriter(
+                    jsonLightOutputContext,
+                    null,
+                    null,
+                    false);
+
+                // write the response
+                await jsonLightWriter.WriteStartAsync(serviceSideResponseResource);
+                await jsonLightWriter.WriteEndAsync();
+
+                // confirm that the written response was the expected response
+                memoryStream.Position = 0;
+                using (var streamReader = new StreamReader(memoryStream))
+                {
+                    var actualResponsePayload = await streamReader.ReadToEndAsync();
+                    Assert.Equal(expectedResponsePayload, actualResponsePayload);
+                }
+            }
+        }
+#endif
+
         [Fact]
         public async Task WriteEntityReferenceLinkForCollectionNavigationPropertyAsync()
         {
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/WriteContextWithDerivedTypeCastAndKeySegmentAsync.xml b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/WriteContextWithDerivedTypeCastAndKeySegmentAsync.xml
new file mode 100644
index 0000000000..62f8053d86
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/JsonLight/WriteContextWithDerivedTypeCastAndKeySegmentAsync.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" xmlns:ags="http://aggregator.microsoft.com/internal" xmlns:odata="http://schemas.microsoft.com/oDataCapabilities">
+  <edmx:DataServices>
+    <Schema Namespace="ns" Alias="self" xmlns="http://docs.oasis-open.org/odata/ns/edm" xmlns:ags="http://aggregator.microsoft.com/internal" xmlns:odata="http://schemas.microsoft.com/oDataCapabilities">
+      <EntityContainer Name="Container">
+        <EntitySet Name="orders" EntityType="self.order" />
+      </EntityContainer>
+      <EntityType Name="order">
+        <Key>
+          <PropertyRef Name="id" />
+        </Key>
+        <Property Name="id" Type="Edm.String" Nullable="false" />
+        <NavigationProperty Name="products" Type="Collection(self.product)" ContainsTarget="true" Nullable="false" />
+      </EntityType>
+      <EntityType Name="product">
+        <Key>
+          <PropertyRef Name="id" />
+        </Key>
+        <Property Name="id" Type="Edm.String" Nullable="false" />
+        <Property Name="name" Type="Edm.String" Nullable="false" />
+      </EntityType>
+      <EntityType Name="derivedProduct" BaseType="self.product">
+      </EntityType>
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/Microsoft.OData.Core.Tests.csproj b/test/FunctionalTests/Microsoft.OData.Core.Tests/Microsoft.OData.Core.Tests.csproj
index 3935c6030e..abe5dc87d9 100644
--- a/test/FunctionalTests/Microsoft.OData.Core.Tests/Microsoft.OData.Core.Tests.csproj
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/Microsoft.OData.Core.Tests.csproj
@@ -51,6 +51,11 @@
     <Compile Remove="Properties\AssemblyInfo.cs" />
   </ItemGroup>
 
+  <ItemGroup>
+    <None Remove="JsonLight\GenerateContextUrlFromSlimUriWithDerivedTypeCastAndKeySegment.xml" />
+    <None Remove="JsonLight\WriteContextWithDerivedTypeCastAndKeySegmentAsync.xml" />
+  </ItemGroup>
+
   <ItemGroup>
     <Compile Include="..\Tests\TestUtils\Common\Microsoft.Test.OData.Utils\Common\ExceptionUtilities.cs" Link="ExceptionUtilities.cs" />
     <Compile Include="..\Tests\TestUtils\Common\Microsoft.Test.OData.Utils\Metadata\EdmConstants.cs" Link="EdmConstants.cs" />
@@ -61,6 +66,11 @@
     <Compile Include="..\Tests\TestUtils\Common\Microsoft.Test.OData.Utils\ODataLibTest\ModelBuilder.cs" Link="ModelBuilder.cs" />
   </ItemGroup>
 
+  <ItemGroup>
+    <EmbeddedResource Include="JsonLight\GenerateContextUrlFromSlimUriWithDerivedTypeCastAndKeySegment.xml" />
+    <EmbeddedResource Include="JsonLight\WriteContextWithDerivedTypeCastAndKeySegmentAsync.xml" />
+  </ItemGroup>
+
   <ItemGroup>
     <ProjectReference Include="..\..\..\src\Microsoft.OData.Core\Microsoft.OData.Core.csproj" />
     <ProjectReference Include="..\..\..\src\Microsoft.OData.Edm\Microsoft.OData.Edm.csproj" />
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/SemanticAst/ODataPathExtensionsTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/SemanticAst/ODataPathExtensionsTests.cs
index 23d9f8aa68..4883294325 100644
--- a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/SemanticAst/ODataPathExtensionsTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/SemanticAst/ODataPathExtensionsTests.cs
@@ -251,6 +251,53 @@ public void TestTrimEndingTypeCast()
             }
         }
 
+        /// <summary>
+        /// Test trimming the end of a path of it's key and type segments
+        /// </summary>
+        [Fact]
+        public void TrimEndingTypeAndKeySegments()
+        {
+            var testCases = new[]
+            {
+                new {
+                    Url = "People",
+                    Trimmed = "People"
+                },
+                new {
+                    Url = "People(1)",
+                    Trimmed = "People"
+                },
+                new {
+                    Url = "People/Fully.Qualified.Namespace.Employee",
+                    Trimmed = "People"
+                },
+                new {
+                    Url = "People(1)/Fully.Qualified.Namespace.Employee",
+                    Trimmed = "People"
+                },
+                new {
+                    Url = "People/Fully.Qualified.Namespace.Employee/1",
+                    Trimmed = "People"
+                },
+                new {
+                    Url = "People/Fully.Qualified.Namespace.Employee/1/MyAddress",
+                    Trimmed = "People/Fully.Qualified.Namespace.Employee/1/MyAddress"
+                },
+                new {
+                    Url = "People(1)/Fully.Qualified.Namespace.Employee/MyAddress",
+                    Trimmed = "People/1/Fully.Qualified.Namespace.Employee/MyAddress"
+                },
+            };
+
+            foreach (var testCase in testCases)
+            {
+                ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, this.testBaseUri, new Uri(this.testBaseUri, testCase.Url));
+                ODataPath path = parser.ParsePath();
+                var result = path.TrimEndingTypeAndKeySegments();
+                Assert.Equal(testCase.Trimmed, result.ToResourcePathString(ODataUrlKeyDelimiter.Slash));
+            }
+        }
+
         [Fact]
         public void TestIsIndividualProperty()
         {
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/System/Collections/Generic/ReadOnlyListExtensionsTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/System/Collections/Generic/ReadOnlyListExtensionsTests.cs
new file mode 100644
index 0000000000..58b9e43d82
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/System/Collections/Generic/ReadOnlyListExtensionsTests.cs
@@ -0,0 +1,24 @@
+namespace System.Collections.Generic
+{
+    using Xunit;
+
+    /// <summary>
+    /// Extensions methods <see cref="IReadOnlyList{T}"/>
+    /// </summary>
+    public sealed class ReadOnlyListExtensionsTests
+    {
+        /// <summary>
+        /// Copied from <see href="https://github.com/dotnet/runtime/blob/87c25589bda5a79baf8d056501663b8525f366a8/src/libraries/System.Runtime/tests/System/ArrayTests.cs#L2040"/>
+        /// </summary>
+        [Fact]
+        public void FindLastIndex()
+        {
+            var intArray = new int[] { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 };
+            Assert.Equal(9, intArray.FindLastIndex(i => i >= 43));
+            Assert.Equal(-1, intArray.FindLastIndex(i => i == 99));
+
+            intArray = new int[0];
+            Assert.Equal(-1, intArray.FindLastIndex(i => i == 43));
+        }
+    }
+}
diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl
index f91c6bb217..f3062d6cec 100644
--- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl
+++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl
@@ -2914,6 +2914,16 @@ public sealed class Microsoft.OData.Edm.EdmUntypedStructuredType : Microsoft.ODa
     Microsoft.OData.Edm.EdmTypeKind TypeKind  { public virtual get; }
 }
 
+[
+ExtensionAttribute(),
+]
+public sealed class System.Collections.Generic.ReadOnlyListExtensions {
+    [
+    ExtensionAttribute(),
+    ]
+    public static int FindLastIndex (IReadOnlyList`1 list, Func`2 predicate)
+}
+
 public enum Microsoft.OData.Edm.Csdl.CsdlTarget : int {
     EntityFramework = 0
     OData = 1
@@ -6408,6 +6418,11 @@ public sealed class Microsoft.OData.UriParser.ODataPathExtensions {
     ]
     public static Microsoft.OData.UriParser.ODataPath TrimEndingKeySegment (Microsoft.OData.UriParser.ODataPath path)
 
+    [
+    ExtensionAttribute(),
+    ]
+    public static Microsoft.OData.UriParser.ODataPath TrimEndingTypeAndKeySegments (Microsoft.OData.UriParser.ODataPath path)
+
     [
     ExtensionAttribute(),
     ]
diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl
index c30f3b01e8..787f26974f 100644
--- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl
+++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl
@@ -2914,6 +2914,16 @@ public sealed class Microsoft.OData.Edm.EdmUntypedStructuredType : Microsoft.ODa
     Microsoft.OData.Edm.EdmTypeKind TypeKind  { public virtual get; }
 }
 
+[
+ExtensionAttribute(),
+]
+public sealed class System.Collections.Generic.ReadOnlyListExtensions {
+    [
+    ExtensionAttribute(),
+    ]
+    public static int FindLastIndex (IReadOnlyList`1 list, Func`2 predicate)
+}
+
 public enum Microsoft.OData.Edm.Csdl.CsdlTarget : int {
     EntityFramework = 0
     OData = 1
@@ -6408,6 +6418,11 @@ public sealed class Microsoft.OData.UriParser.ODataPathExtensions {
     ]
     public static Microsoft.OData.UriParser.ODataPath TrimEndingKeySegment (Microsoft.OData.UriParser.ODataPath path)
 
+    [
+    ExtensionAttribute(),
+    ]
+    public static Microsoft.OData.UriParser.ODataPath TrimEndingTypeAndKeySegments (Microsoft.OData.UriParser.ODataPath path)
+
     [
     ExtensionAttribute(),
     ]
diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl
index f91c6bb217..f3062d6cec 100644
--- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl
+++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl
@@ -2914,6 +2914,16 @@ public sealed class Microsoft.OData.Edm.EdmUntypedStructuredType : Microsoft.ODa
     Microsoft.OData.Edm.EdmTypeKind TypeKind  { public virtual get; }
 }
 
+[
+ExtensionAttribute(),
+]
+public sealed class System.Collections.Generic.ReadOnlyListExtensions {
+    [
+    ExtensionAttribute(),
+    ]
+    public static int FindLastIndex (IReadOnlyList`1 list, Func`2 predicate)
+}
+
 public enum Microsoft.OData.Edm.Csdl.CsdlTarget : int {
     EntityFramework = 0
     OData = 1
@@ -6408,6 +6418,11 @@ public sealed class Microsoft.OData.UriParser.ODataPathExtensions {
     ]
     public static Microsoft.OData.UriParser.ODataPath TrimEndingKeySegment (Microsoft.OData.UriParser.ODataPath path)
 
+    [
+    ExtensionAttribute(),
+    ]
+    public static Microsoft.OData.UriParser.ODataPath TrimEndingTypeAndKeySegments (Microsoft.OData.UriParser.ODataPath path)
+
     [
     ExtensionAttribute(),
     ]