From 3acc0281217e4a0405b56a63e324dce0c209a59d Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Wed, 20 Nov 2024 14:46:24 -0800 Subject: [PATCH 1/3] Fixes #2861: Pass the IServiceProvider to ODataUriParser --- .../ODataResourceDeserializerHelpers.cs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs b/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs index 3881ed869..9454e2ed3 100644 --- a/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs +++ b/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs @@ -91,7 +91,17 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe { try { - path = new Routing.ODataPath(new ODataUriParser(readContext.Model, new Uri(navigationSource.Path.Path, UriKind.Relative)).ParsePath()); + ODataUriParser parser; + if (readContext != null && readContext.InternalRequest != null && readContext.InternalRequest.RequestContainer != null) + { + parser = new ODataUriParser(readContext.Model, new Uri(navigationSource.Path.Path, UriKind.Relative), readContext.InternalRequest.RequestContainer); + } + else + { + parser = new ODataUriParser(readContext.Model, new Uri(navigationSource.Path.Path, UriKind.Relative)); + } + + path = new Routing.ODataPath(parser.ParsePath()); } catch (ODataException) { @@ -332,7 +342,16 @@ internal static Routing.ODataPath ApplyIdToPath(ODataDeserializerContext readCon try { - ODataUriParser parser = new ODataUriParser(readContext.Model, new Uri(serviceRoot), resourceWrapper.ResourceBase.Id); + ODataUriParser parser; + if (internalRequest.RequestContainer != null) + { + parser = new ODataUriParser(readContext.Model, new Uri(serviceRoot), resourceWrapper.ResourceBase.Id, internalRequest.RequestContainer); + } + else + { + parser = new ODataUriParser(readContext.Model, new Uri(serviceRoot), resourceWrapper.ResourceBase.Id); + } + odataPath = parser.ParsePath(); } catch (ODataException) From 2811394f5d6da983659b21709cbae7d0c549e330 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Thu, 21 Nov 2024 14:29:37 -0800 Subject: [PATCH 2/3] Update src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs Co-authored-by: John Gathogo --- .../Deserialization/ODataResourceDeserializerHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs b/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs index 9454e2ed3..1b4e2edb3 100644 --- a/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs +++ b/src/Microsoft.AspNet.OData.Shared/Formatter/Deserialization/ODataResourceDeserializerHelpers.cs @@ -92,7 +92,7 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe try { ODataUriParser parser; - if (readContext != null && readContext.InternalRequest != null && readContext.InternalRequest.RequestContainer != null) + if (readContext?.InternalRequest?.RequestContainer != null) { parser = new ODataUriParser(readContext.Model, new Uri(navigationSource.Path.Path, UriKind.Relative), readContext.InternalRequest.RequestContainer); } From a4a71cbdfa897adae53d184a84fd2af7db90b433 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Fri, 22 Nov 2024 14:00:33 -0800 Subject: [PATCH 3/3] Add a test to verify the injected ODataUriResolver --- .../Microsoft.AspNetCore.OData.csproj | 16 +++++ .../ODataResourceDeserializerTests.cs | 61 +++++++++++++++++++ .../Microsoft.AspNetCore.OData.Test.csproj | 12 ++++ 3 files changed, 89 insertions(+) diff --git a/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.csproj b/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.csproj index 5247dfb1d..2565b14be 100644 --- a/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.csproj +++ b/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.csproj @@ -13,6 +13,22 @@ false + + False + + + + False + + + + False + + + + False + + diff --git a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Formatter/Deserialization/ODataResourceDeserializerTests.cs b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Formatter/Deserialization/ODataResourceDeserializerTests.cs index b95cc73f9..5d91a5487 100644 --- a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Formatter/Deserialization/ODataResourceDeserializerTests.cs +++ b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Formatter/Deserialization/ODataResourceDeserializerTests.cs @@ -14,6 +14,7 @@ using System.Net.Http.Headers; using System.Runtime.Serialization; using Microsoft.AspNet.OData.Builder; +using Microsoft.AspNet.OData.Extensions; using Microsoft.AspNet.OData.Formatter; using Microsoft.AspNet.OData.Formatter.Deserialization; using Microsoft.AspNet.OData.Formatter.Serialization; @@ -21,6 +22,7 @@ using Microsoft.AspNet.OData.Test.Builder; using Microsoft.AspNet.OData.Test.Common; using Microsoft.AspNet.OData.Test.Common.Types; +using Microsoft.AspNetCore.Mvc; using Microsoft.OData; using Microsoft.OData.Edm; using Microsoft.OData.UriParser; @@ -1939,6 +1941,65 @@ public void ApplyIdToPath_CreatesODataPathWithNullKeySegment_IfKeyValueNotSet() Assert.Equal("Products('')", value); } + [Fact] + public void ApplyIdToPath_CreatesODataPathWithNullKeySegment_IfKeyValueNotSet2() + { + ODataResource resource = new ODataResource { TypeName = _productEdmType.FullName(), Id = new Uri("Products('42')", UriKind.RelativeOrAbsolute) }; + ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(resource); + var currentContext = new ODataDeserializerContext + { + Model = _edmModel, + Path = _readContext.Path, + Request = RequestFactory.CreateFromModel(_edmModel) + }; + + int test = 0; + + IServiceProvider container = new MockContainer(builder => + { + builder.AddService(ServiceLifetime.Singleton, sp => _edmModel); + builder.AddService(ServiceLifetime.Singleton, typeof(ODataUriResolver), sp => new MyUriResolver(() => { test++; })); + }); + +#if NETCORE + currentContext.Request.ODataFeature().RouteName = "Route"; + currentContext.Request.ODataFeature().RequestContainer = container; +#else + currentContext.Request.Properties["Microsoft.AspNet.OData.RequestContainer"] = container; +#endif + + ODataPath path = ODataResourceDeserializerHelpers.ApplyIdToPath(currentContext, resourceWrapper); + + Assert.NotNull(path); + string value = path.ToString(); + + Assert.Equal(1, test); + Assert.Equal("Products(42)", value); + } + + public class MyUriResolver : ODataUriResolver + { + public MyUriResolver(Action action) + { + Action = action; + } + + public Action Action { get; } + + public override IEnumerable> ResolveKeys(IEdmEntityType type, IList positionalValues, Func convertFunc) + { + Action(); + + IList newValues = new List(positionalValues.Count); + foreach (var v in positionalValues) + { + newValues.Add(v.Trim('\'')); + } + + return base.ResolveKeys(type, newValues, convertFunc); + } + } + private static ODataMessageReader GetODataMessageReader(IODataRequestMessage oDataRequestMessage, IEdmModel edmModel) { return new ODataMessageReader(oDataRequestMessage, new ODataMessageReaderSettings(), edmModel); diff --git a/test/UnitTest/Microsoft.AspNetCore.OData.Test/Microsoft.AspNetCore.OData.Test.csproj b/test/UnitTest/Microsoft.AspNetCore.OData.Test/Microsoft.AspNetCore.OData.Test.csproj index 3647b0e20..f64b3473f 100644 --- a/test/UnitTest/Microsoft.AspNetCore.OData.Test/Microsoft.AspNetCore.OData.Test.csproj +++ b/test/UnitTest/Microsoft.AspNetCore.OData.Test/Microsoft.AspNetCore.OData.Test.csproj @@ -11,6 +11,18 @@ false + + False + + + False + + + False + + + False +