diff --git a/src/Dapr.Actors/Runtime/ActorManager.cs b/src/Dapr.Actors/Runtime/ActorManager.cs index d766cd485..80049d65f 100644 --- a/src/Dapr.Actors/Runtime/ActorManager.cs +++ b/src/Dapr.Actors/Runtime/ActorManager.cs @@ -186,7 +186,13 @@ async Task RequestFunc(Actor actor, CancellationToken ct) // Serialize result if it has result (return type was not just Task.) if (methodInfo.ReturnType.Name != typeof(Task).Name) { - await JsonSerializer.SerializeAsync(responseBodyStream, result, result.GetType(), jsonSerializerOptions); +#if NET7_0_OR_GREATER + var resultType = methodInfo.ReturnType.GenericTypeArguments[0]; + await JsonSerializer.SerializeAsync(responseBodyStream, result, resultType, jsonSerializerOptions); +#else + await JsonSerializer.SerializeAsync(responseBodyStream, result, jsonSerializerOptions); +#endif + } } diff --git a/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/DerivedResponse.cs b/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/DerivedResponse.cs new file mode 100644 index 000000000..c11f547e7 --- /dev/null +++ b/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/DerivedResponse.cs @@ -0,0 +1,20 @@ +// ------------------------------------------------------------------------ +// Copyright 2021 The Dapr Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + +namespace Dapr.E2E.Test.Actors.WeaklyTypedTesting +{ + public class DerivedResponse : ResponseBase + { + public string DerivedProperty { get; set; } + } +} diff --git a/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/IWeaklyTypedTestingActor.cs b/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/IWeaklyTypedTestingActor.cs new file mode 100644 index 000000000..2c5d1e82d --- /dev/null +++ b/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/IWeaklyTypedTestingActor.cs @@ -0,0 +1,25 @@ +// ------------------------------------------------------------------------ +// Copyright 2021 The Dapr Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + +using System.Threading.Tasks; +using Dapr.Actors; + +namespace Dapr.E2E.Test.Actors.WeaklyTypedTesting +{ + public interface IWeaklyTypedTestingActor : IPingActor, IActor + { + Task GetPolymorphicResponse(); + + Task GetNullResponse(); + } +} diff --git a/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/ResponseBase.cs b/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/ResponseBase.cs new file mode 100644 index 000000000..45736d808 --- /dev/null +++ b/test/Dapr.E2E.Test.Actors/WeaklyTypedTesting/ResponseBase.cs @@ -0,0 +1,25 @@ +// ------------------------------------------------------------------------ +// Copyright 2021 The Dapr Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + +using System.Text.Json.Serialization; + +namespace Dapr.E2E.Test.Actors.WeaklyTypedTesting +{ +#if NET7_0_OR_GREATER + [JsonDerivedType(typeof(DerivedResponse), typeDiscriminator: nameof(DerivedResponse))] +#endif + public class ResponseBase + { + public string BasePropeprty { get; set; } + } +} diff --git a/test/Dapr.E2E.Test.App/Actors/WeaklyTypedTestingActor.cs b/test/Dapr.E2E.Test.App/Actors/WeaklyTypedTestingActor.cs new file mode 100644 index 000000000..3cbe20bad --- /dev/null +++ b/test/Dapr.E2E.Test.App/Actors/WeaklyTypedTestingActor.cs @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------------ +// Copyright 2021 The Dapr Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ + +using System.Threading.Tasks; +using Dapr.Actors.Runtime; + +namespace Dapr.E2E.Test.Actors.WeaklyTypedTesting +{ + public class WeaklyTypedTestingActor : Actor, IWeaklyTypedTestingActor + { + public WeaklyTypedTestingActor(ActorHost host) + : base(host) + { + } + + public Task GetNullResponse() + { + return Task.FromResult(null); + } + + public Task GetPolymorphicResponse() + { + var response = new DerivedResponse + { + BasePropeprty = "Base property value", + DerivedProperty = "Derived property value" + }; + + return Task.FromResult(response); + } + + public Task Ping() + { + return Task.CompletedTask; + } + } +} diff --git a/test/Dapr.E2E.Test.App/Startup.cs b/test/Dapr.E2E.Test.App/Startup.cs index bd0de7b91..bfca60f91 100644 --- a/test/Dapr.E2E.Test.App/Startup.cs +++ b/test/Dapr.E2E.Test.App/Startup.cs @@ -19,6 +19,7 @@ namespace Dapr.E2E.Test using Dapr.E2E.Test.Actors.State; using Dapr.E2E.Test.Actors.ExceptionTesting; using Dapr.E2E.Test.Actors.Serialization; + using Dapr.E2E.Test.Actors.WeaklyTypedTesting; using Dapr.E2E.Test.App.ErrorTesting; using Dapr.Workflow; using Microsoft.AspNetCore.Authentication; @@ -106,6 +107,7 @@ public void ConfigureServices(IServiceCollection services) options.Actors.RegisterActor(); options.Actors.RegisterActor(); options.Actors.RegisterActor(); + options.Actors.RegisterActor(); }); } diff --git a/test/Dapr.E2E.Test/Actors/E2ETests.WeaklyTypedTests.cs b/test/Dapr.E2E.Test/Actors/E2ETests.WeaklyTypedTests.cs new file mode 100644 index 000000000..b250d731e --- /dev/null +++ b/test/Dapr.E2E.Test/Actors/E2ETests.WeaklyTypedTests.cs @@ -0,0 +1,68 @@ +// ------------------------------------------------------------------------ +// Copyright 2021 The Dapr Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------ +namespace Dapr.E2E.Test +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using Dapr.Actors; + using Dapr.E2E.Test.Actors.WeaklyTypedTesting; + using FluentAssertions; + using Xunit; + + public partial class E2ETests : IAsyncLifetime + { +#if NET8_0_OR_GREATER + [Fact] + public async Task WeaklyTypedActorCanReturnPolymorphicResponse() + { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); + var pingProxy = this.ProxyFactory.CreateActorProxy(ActorId.CreateRandom(), "WeaklyTypedTestingActor"); + var proxy = this.ProxyFactory.Create(ActorId.CreateRandom(), "WeaklyTypedTestingActor"); + + await WaitForActorRuntimeAsync(pingProxy, cts.Token); + + var result = await proxy.InvokeMethodAsync(nameof(IWeaklyTypedTestingActor.GetPolymorphicResponse)); + + result.Should().BeOfType().Which.DerivedProperty.Should().NotBeNullOrWhiteSpace(); + } +#else + [Fact] + public async Task WeaklyTypedActorCanReturnDerivedResponse() + { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); + var pingProxy = this.ProxyFactory.CreateActorProxy(ActorId.CreateRandom(), "WeaklyTypedTestingActor"); + var proxy = this.ProxyFactory.Create(ActorId.CreateRandom(), "WeaklyTypedTestingActor"); + + await WaitForActorRuntimeAsync(pingProxy, cts.Token); + + var result = await proxy.InvokeMethodAsync(nameof(IWeaklyTypedTestingActor.GetPolymorphicResponse)); + + result.Should().BeOfType().Which.DerivedProperty.Should().NotBeNullOrWhiteSpace(); + } +#endif + [Fact] + public async Task WeaklyTypedActorCanReturnNullResponse() + { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); + var pingProxy = this.ProxyFactory.CreateActorProxy(ActorId.CreateRandom(), "WeaklyTypedTestingActor"); + var proxy = this.ProxyFactory.Create(ActorId.CreateRandom(), "WeaklyTypedTestingActor"); + + await WaitForActorRuntimeAsync(pingProxy, cts.Token); + + var result = await proxy.InvokeMethodAsync(nameof(IWeaklyTypedTestingActor.GetNullResponse)); + + result.Should().BeNull(); + } + } +}