-
Notifications
You must be signed in to change notification settings - Fork 345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Weakly-typed actors should support polymorphic response and null response #1214
Weakly-typed actors should support polymorphic response and null response #1214
Conversation
1530e1f
to
267ac97
Compare
var returnType = methodInfo.ReturnType.GenericTypeArguments[0]; | ||
await JsonSerializer.SerializeAsync(responseBodyStream, result, returnType, jsonSerializerOptions); | ||
#else | ||
await JsonSerializer.SerializeAsync<object>(responseBodyStream, result, jsonSerializerOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first inclination is to not change the existing behavior for .NET 6 (and, by extension, .NET 7 given we don't ship that specific target), as that would be an invisible change that has potential privacy/security concerns if unexpected properties were serialized. If users desire the polymorphic serialization behavior, they can move to .NET 8 and use the new serialization attributes.
(If there was significant push by users to support the serialization behavior on .NET 6, then I suppose some sort of flag could exist in the options object, but I feel that it would need to be opt-in. Still, the attributes feel like a better approach.)
That said, null
responses should be supported, so I appreciate the fix for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reviewing the PR. As I understood things, apart from supporting null
responses my change did not change the behavior in .NET 6. I understood that in .NET 6 for a non-null response
await JsonSerializer.SerializeAsync(responseBodyStream, result, result.GetType(), jsonSerializerOptions);
and
await JsonSerializer.SerializeAsync<object>(responseBodyStream, result, jsonSerializerOptions);
produce the same json. And as the current version of the code uses the runtime type the json includes properties of derived classes. The E2E tests I added assert that for .NET 6 my change does the same. As such my change should not introduce new privacy or security concerns. But please correct me if I'm wrong.
I'm not sure I understand your comment regarding adding some sort of flag on the options object to support polymorphic (de)serialization in .NET 6. As System.Text.Json in .NET 6 does not support polymorphic (de)serialization out-of-the-box I don't think Dapr needs to support it and a flag is not needed for .NET 6.
System.Text.Json in .NET 7 does support polymorphic (de)serialization out-of-the-box, provided we serialize using the declared type on the interface instead of the runtime type as follows:
var returnType = methodInfo.ReturnType.GenericTypeArguments[0];
await JsonSerializer.SerializeAsync(responseBodyStream, result, returnType, jsonSerializerOptions);
I think using the declared type instead of the runtime type should be the default in .NET 7 or later. Again, no flag needed. If programmers require polymorphic (de)serialization then they can use the JsonDerivedTypeAttribute or, as I prefer, write a JsonTypeInfoResolver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the docs again, you're right, there's no change to the existing .NET 6 usage, so I retract my earlier comments.
This would still represent a breaking change for users of the SDK that rely on the .NET 6 polymorphic behavior when they move to .NET 8 though, right, in that they'd need to decorate their model types with the appropriate attributes? (I agree that that seems like the best approach.) Given that, we'd need to make sure there was adequate documentation of that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would still represent a breaking change for users of the SDK that rely on the .NET 6 polymorphic behavior when they move to .NET 8 though, right
Correct, that would be a breaking change. Although one could argue in .NET 6 one has polymorphic serialization, not polymorphic deserialization, but it is exactly the serialization of derived properties that would break when moving to .NET 8.
we'd need to make sure there was adequate documentation of that change
As in a release note?
Or as in Dapr docs somewhere in https://docs.dapr.io/developing-applications/sdks/dotnet/dotnet-actors/ ?
The Dapr docs have no current mention on polymorphism. It would be good to write about polymorphism in the Dapr docs for both weakly-typed and strongly-typed actors using both DataContractSerializer and json serializer. And also for service invocation.
The E2E tests I added for this change are also the first tests on polymorphism in the .NET SDK if I'm not mistaken. I only added E2E to test polymorphism in a response object for weakly-typed actors, because that was not currently working. It would be good to also add E2E tests for polymorphism in a request object in weakly typed actors. And for both request and ressponse objects in strongly-typed actors using both the DataContractSerializer and the newly added support for json serialization in strongly-typed actors. But I think it is best to add those additional tests in a separate PR so that this PR remains focussed on the fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in a release note?
Or as in Dapr docs somewhere in https://docs.dapr.io/developing-applications/sdks/dotnet/dotnet-actors/ ?
At a minimum, there should be a note in the release docs related to the implicit change in behavior. Having general docs on Dapr serialization and polymorphism would be great but no necessarily required (given there is ample MS docs on the subject). Still, there have been other places where having a basic summary of .NET behavior can be helpful (see #1199) to a Dapr developer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1199 is now #1222 since I had a typo in the DCO. @RemcoBlok I'd encourage you to type up the documentation in the actors for your changes so it's available immediately in the next release instead of being lost in this PR thread indefinitely. There's a flag you can request they add linking the docs to your PR here so one isn't accepted without the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks all for your replies. I've been travelling and not had a chance to respond earlier. I have some text for a release note. Is it best to discuss that in the issue I created related to the PR instead of here? The issue template seemed to suggest that the release notes are picked up from the issue, not the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thoughts, let's discuss the release note here so that we don't have to jump between threads.
Release Note
Weakly-typed actor should support polymorphic response.
Problem
The .NET 6 and .NET 8 targets of the Dapr SDK have different serialization behavior of properties of a derived response object on an operation of a weakly-typed actor client.
Impact
Impacts users upgrading a consumer application to .NET 8 running Dapr <version>
or later.
Root Cause
In the .NET 6 target of the SDK the actor runtime serializes the response object on an operation of a weakly-typed actor client using the runtime type of the response object. In the .NET 8 target of the SDK the actor runtime serializes the response object using the base response type as declared on the operation on the actor interface.
Solution
The programmer must decorate the base response class that is declared on the operation on the actor interface with a JsonDerivedType
attribute specifying the derived response class.
Alternatively, a custom IJsonTypeInfoResolver
implementation can be set on the JsonSerializerOptions.TypeInfoResolver
property adding a JsonDerivedType
instance to the JsonPolymorphismOptions.DerivedTypes
property on the JsonTypeInfo.PolymorphismOptions
property.
Note that while .NET 7 introduced polymorphic (de)serialization using JsonDerivedType
attribute or JsonPolymorphismOptions
on a custom IJsonTypeInfoResolver
implementation, Dapr does not ship a .NET 7 target of the SDK. Hence, a .NET 7 consumer application uses the .NET 6 target of the Dapr SDK. Therefore, this breaking change only applies when upgrading a consumer application to .NET 8.
Note that the new serialization behavior in the .NET 8 version of the SDK allows for polymorphic deserialization of the response by a weakly-typed actor client. This requires that the programmer specifies a typeDiscriminator
on the JsonDerivedType
attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philliphoff I noticed the regression tests for .NET 7 failed. Not sure why. Can you kick off the test again please?
aa917ea
to
b3b4857
Compare
b3b4857
to
b0bdc4e
Compare
@RemcoBlok It looks like this is good, pending abiding by the DCO (sign-off) policy. |
Signed-off-by: Remco Blok <[email protected]>
b0bdc4e
to
4e2bba0
Compare
resolved the DCO issue. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1214 +/- ##
==========================================
+ Coverage 68.47% 68.48% +0.01%
==========================================
Files 172 172
Lines 5846 5848 +2
Branches 648 648
==========================================
+ Hits 4003 4005 +2
Misses 1681 1681
Partials 162 162
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
@philliphoff It would appear the integration tests for .NET 7.0 fail occasionally. Last time they succeeded when trying again. I'm sure this occasional failure is not related to this PR. Could you try again please? |
@philliphoff Thanks for approving the PR! |
@RemcoBlok Thanks for the contribution! |
Signed-off-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Signed-off-by: James Croft <[email protected]>
Signed-off-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Signed-off-by: James Croft <[email protected]>
* Added documentation detailing how serialization works using the DataContract serialization framework. (#1222) Signed-off-by: Whit Waldo <[email protected]> Signed-off-by: James Croft <[email protected]> * Weakly typed actor polymorphic and null responses (#1214) Signed-off-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Signed-off-by: James Croft <[email protected]> * Enable vault name mapping and error suppression Signed-off-by: Yash Nisar <[email protected]> Signed-off-by: James Croft <[email protected]> * Add additional secret descriptor constructor for required without key map Signed-off-by: James Croft <[email protected]> * Update configuration load exception rethrow to match rules Signed-off-by: James Croft <[email protected]> * Add tests for required/not required exception handling Signed-off-by: James Croft <[email protected]> * Implementing Cryptography building block in .NET (#1217) * Added method to DaprClient and GRPC implementation to call cryptography proto endpoints Signed-off-by: Whit Waldo <[email protected]> * First pass at implementing all exposed Cryptography methods on Go interface Signed-off-by: Whit Waldo <[email protected]> * Added examples for Cryptography block Signed-off-by: Whit Waldo <[email protected]> * Added missing copyright statements Signed-off-by: Whit Waldo <[email protected]> * Updated to properly support Crypto API this time Signed-off-by: Whit Waldo <[email protected]> * Added copyright statements Signed-off-by: Whit Waldo <[email protected]> * Removed deprecated examples as the subtle APIs are presently disabled Signed-off-by: Whit Waldo <[email protected]> * Updated example to reflect new API shape Signed-off-by: Whit Waldo <[email protected]> * Updated example and readme Signed-off-by: Whit Waldo <[email protected]> * Added overloads for encrypting/decrypting streams instead of just fixed byte arrays. Added example demonstrating the same encrypting a file via a FileStream and decrypting from a MemoryStream. Signed-off-by: Whit Waldo <[email protected]> * Added some unit tests to pair with the implementation Signed-off-by: Whit Waldo <[email protected]> * Added null check for the stream argument Signed-off-by: Whit Waldo <[email protected]> * Changed case of the arguments as they should read "plaintext" and not "plainText" Signed-off-by: Whit Waldo <[email protected]> * Reduced number of encryption implementations by just wrapping byte array into memory stream Signed-off-by: Whit Waldo <[email protected]> * Constrainted returned member types per review suggestion Signed-off-by: Whit Waldo <[email protected]> * Updated methods to use ReadOnlyMemory<byte> instead of byte[] - updated implementations to use low-allocation spans where possible (though ToArray is necessary to wrap with MemoryStream). Signed-off-by: Whit Waldo <[email protected]> * Updated to use encryption/decryption options instead of lots of method overload variations. Simplified gRPC implementation to use fewer methods. Applied argument name updates applied previously (plainText -> plaintext). Signed-off-by: Whit Waldo <[email protected]> * Updated tests Signed-off-by: Whit Waldo <[email protected]> * Removed unused reference Signed-off-by: Whit Waldo <[email protected]> * Updated examples to reflect new method shapes. Downgraded package to .net 6 instead of .net 8 per review suggestion. Signed-off-by: Whit Waldo <[email protected]> * Updated to reflect non-aliased values per review suggestion Signed-off-by: Whit Waldo <[email protected]> * Update to ensure that both send/receive streams run at the same time instead of sequentially. Signed-off-by: Whit Waldo <[email protected]> * Updated to support streamed results in addition to fixed byte arrays. Refactored implementation to minimize duplicative code. Signed-off-by: Whit Waldo <[email protected]> * Updated example to fix compile issue Signed-off-by: Whit Waldo <[email protected]> * Removed encrypt/decrypt methods that accepted streams and returned ReadOnlyMemory<byte>. Marked implementations that use this on the gRPC class as private instead. Signed-off-by: Whit Waldo <[email protected]> * Added missing Obsolete attributes on Encrypt/Decrypt methods. Added overloads on decrypt methods that do not require a DecryptionOptions to be passed in. Signed-off-by: Whit Waldo <[email protected]> * Updated encrypt/decrypt options so the streaming block size no longer uses a uint. Added validation in its place to ensure the value provided is never less than or equal to 0. Signed-off-by: Whit Waldo <[email protected]> * Updated how validation works in the options to accommodate lack of the shorter variation in .NET 6 Signed-off-by: Whit Waldo <[email protected]> * Updated names of encrypt/decrypt streaming methods so everything uses just EncryptAsync or DecryptAsync Signed-off-by: Whit Waldo <[email protected]> * Fixed regression that would have prevented data from being sent entirely to the sidecar. Also simplified operation per suggestion in review. Signed-off-by: Whit Waldo <[email protected]> * Updated examples to reflect changed API Signed-off-by: Whit Waldo <[email protected]> * Updated so IAsyncEnumerable methods (encrypt and decrypt) return IAsyncEnumerable<ReadOnlyMemory<byte>> instead of IAsyncEnumerable<byte[]>. Signed-off-by: Whit Waldo <[email protected]> * Updated example to reflect change from IAsyncEnumerable<byte> to IAsyncEnumerable<ReadOnlyMemory<byte>> Signed-off-by: Whit Waldo <[email protected]> * Avoiding allocation by using MemoryMarshal instead of .ToArray() to create MemoryStream from ReadOnlyMemory<byte>. Signed-off-by: Whit Waldo <[email protected]> * Performance updates to minimize unnecessary byte array copies and eliminate unnecessary allocations. Signed-off-by: Whit Waldo <[email protected]> * Removed unnecessary return from SendPlaintextStreamAsync and SendCiphertextStreamAsync methods Signed-off-by: Whit Waldo <[email protected]> * Updated exception text to be more specific as to what's wrong with the input value. Signed-off-by: Whit Waldo <[email protected]> * Minor tweak to prefer using using a Memory Signed-off-by: Whit Waldo <[email protected]> * Deduplicated some of the Decrypt methods, simplifying the implementation Signed-off-by: Whit Waldo <[email protected]> * Eliminated duplicate encryption method, simplifying implementation Signed-off-by: Whit Waldo <[email protected]> * Updated to eliminate an unnecessary `await` and `async foreach`. Signed-off-by: Whit Waldo <[email protected]> * Updated stream example to reflect the changes to the API shape Signed-off-by: Whit Waldo <[email protected]> * Added notes about operations with stream-based data Signed-off-by: Whit Waldo <[email protected]> --------- Signed-off-by: Whit Waldo <[email protected]> Signed-off-by: James Croft <[email protected]> * Update DaprSecretDescriptor constructors and documentation Signed-off-by: James Croft Signed-off-by: James Croft <[email protected]> * Remove DaprSecretStoreConfigurationProvider Console.WriteLine Signed-off-by: James Croft <[email protected]> --------- Signed-off-by: Whit Waldo <[email protected]> Signed-off-by: James Croft <[email protected]> Signed-off-by: Remco Blok <[email protected]> Signed-off-by: Yash Nisar <[email protected]> Signed-off-by: James Croft Co-authored-by: Whit Waldo <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Co-authored-by: Yash Nisar <[email protected]>
Signed-off-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Signed-off-by: Divya Perumal <[email protected]>
* Added documentation detailing how serialization works using the DataContract serialization framework. (dapr#1222) Signed-off-by: Whit Waldo <[email protected]> Signed-off-by: James Croft <[email protected]> * Weakly typed actor polymorphic and null responses (dapr#1214) Signed-off-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Signed-off-by: James Croft <[email protected]> * Enable vault name mapping and error suppression Signed-off-by: Yash Nisar <[email protected]> Signed-off-by: James Croft <[email protected]> * Add additional secret descriptor constructor for required without key map Signed-off-by: James Croft <[email protected]> * Update configuration load exception rethrow to match rules Signed-off-by: James Croft <[email protected]> * Add tests for required/not required exception handling Signed-off-by: James Croft <[email protected]> * Implementing Cryptography building block in .NET (dapr#1217) * Added method to DaprClient and GRPC implementation to call cryptography proto endpoints Signed-off-by: Whit Waldo <[email protected]> * First pass at implementing all exposed Cryptography methods on Go interface Signed-off-by: Whit Waldo <[email protected]> * Added examples for Cryptography block Signed-off-by: Whit Waldo <[email protected]> * Added missing copyright statements Signed-off-by: Whit Waldo <[email protected]> * Updated to properly support Crypto API this time Signed-off-by: Whit Waldo <[email protected]> * Added copyright statements Signed-off-by: Whit Waldo <[email protected]> * Removed deprecated examples as the subtle APIs are presently disabled Signed-off-by: Whit Waldo <[email protected]> * Updated example to reflect new API shape Signed-off-by: Whit Waldo <[email protected]> * Updated example and readme Signed-off-by: Whit Waldo <[email protected]> * Added overloads for encrypting/decrypting streams instead of just fixed byte arrays. Added example demonstrating the same encrypting a file via a FileStream and decrypting from a MemoryStream. Signed-off-by: Whit Waldo <[email protected]> * Added some unit tests to pair with the implementation Signed-off-by: Whit Waldo <[email protected]> * Added null check for the stream argument Signed-off-by: Whit Waldo <[email protected]> * Changed case of the arguments as they should read "plaintext" and not "plainText" Signed-off-by: Whit Waldo <[email protected]> * Reduced number of encryption implementations by just wrapping byte array into memory stream Signed-off-by: Whit Waldo <[email protected]> * Constrainted returned member types per review suggestion Signed-off-by: Whit Waldo <[email protected]> * Updated methods to use ReadOnlyMemory<byte> instead of byte[] - updated implementations to use low-allocation spans where possible (though ToArray is necessary to wrap with MemoryStream). Signed-off-by: Whit Waldo <[email protected]> * Updated to use encryption/decryption options instead of lots of method overload variations. Simplified gRPC implementation to use fewer methods. Applied argument name updates applied previously (plainText -> plaintext). Signed-off-by: Whit Waldo <[email protected]> * Updated tests Signed-off-by: Whit Waldo <[email protected]> * Removed unused reference Signed-off-by: Whit Waldo <[email protected]> * Updated examples to reflect new method shapes. Downgraded package to .net 6 instead of .net 8 per review suggestion. Signed-off-by: Whit Waldo <[email protected]> * Updated to reflect non-aliased values per review suggestion Signed-off-by: Whit Waldo <[email protected]> * Update to ensure that both send/receive streams run at the same time instead of sequentially. Signed-off-by: Whit Waldo <[email protected]> * Updated to support streamed results in addition to fixed byte arrays. Refactored implementation to minimize duplicative code. Signed-off-by: Whit Waldo <[email protected]> * Updated example to fix compile issue Signed-off-by: Whit Waldo <[email protected]> * Removed encrypt/decrypt methods that accepted streams and returned ReadOnlyMemory<byte>. Marked implementations that use this on the gRPC class as private instead. Signed-off-by: Whit Waldo <[email protected]> * Added missing Obsolete attributes on Encrypt/Decrypt methods. Added overloads on decrypt methods that do not require a DecryptionOptions to be passed in. Signed-off-by: Whit Waldo <[email protected]> * Updated encrypt/decrypt options so the streaming block size no longer uses a uint. Added validation in its place to ensure the value provided is never less than or equal to 0. Signed-off-by: Whit Waldo <[email protected]> * Updated how validation works in the options to accommodate lack of the shorter variation in .NET 6 Signed-off-by: Whit Waldo <[email protected]> * Updated names of encrypt/decrypt streaming methods so everything uses just EncryptAsync or DecryptAsync Signed-off-by: Whit Waldo <[email protected]> * Fixed regression that would have prevented data from being sent entirely to the sidecar. Also simplified operation per suggestion in review. Signed-off-by: Whit Waldo <[email protected]> * Updated examples to reflect changed API Signed-off-by: Whit Waldo <[email protected]> * Updated so IAsyncEnumerable methods (encrypt and decrypt) return IAsyncEnumerable<ReadOnlyMemory<byte>> instead of IAsyncEnumerable<byte[]>. Signed-off-by: Whit Waldo <[email protected]> * Updated example to reflect change from IAsyncEnumerable<byte> to IAsyncEnumerable<ReadOnlyMemory<byte>> Signed-off-by: Whit Waldo <[email protected]> * Avoiding allocation by using MemoryMarshal instead of .ToArray() to create MemoryStream from ReadOnlyMemory<byte>. Signed-off-by: Whit Waldo <[email protected]> * Performance updates to minimize unnecessary byte array copies and eliminate unnecessary allocations. Signed-off-by: Whit Waldo <[email protected]> * Removed unnecessary return from SendPlaintextStreamAsync and SendCiphertextStreamAsync methods Signed-off-by: Whit Waldo <[email protected]> * Updated exception text to be more specific as to what's wrong with the input value. Signed-off-by: Whit Waldo <[email protected]> * Minor tweak to prefer using using a Memory Signed-off-by: Whit Waldo <[email protected]> * Deduplicated some of the Decrypt methods, simplifying the implementation Signed-off-by: Whit Waldo <[email protected]> * Eliminated duplicate encryption method, simplifying implementation Signed-off-by: Whit Waldo <[email protected]> * Updated to eliminate an unnecessary `await` and `async foreach`. Signed-off-by: Whit Waldo <[email protected]> * Updated stream example to reflect the changes to the API shape Signed-off-by: Whit Waldo <[email protected]> * Added notes about operations with stream-based data Signed-off-by: Whit Waldo <[email protected]> --------- Signed-off-by: Whit Waldo <[email protected]> Signed-off-by: James Croft <[email protected]> * Update DaprSecretDescriptor constructors and documentation Signed-off-by: James Croft Signed-off-by: James Croft <[email protected]> * Remove DaprSecretStoreConfigurationProvider Console.WriteLine Signed-off-by: James Croft <[email protected]> --------- Signed-off-by: Whit Waldo <[email protected]> Signed-off-by: James Croft <[email protected]> Signed-off-by: Remco Blok <[email protected]> Signed-off-by: Yash Nisar <[email protected]> Signed-off-by: James Croft Co-authored-by: Whit Waldo <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Remco Blok <[email protected]> Co-authored-by: Phillip Hoff <[email protected]> Co-authored-by: Yash Nisar <[email protected]> Signed-off-by: Divya Perumal <[email protected]>
In .NET 7.0 or later an operation on an actor invoked using a weakly-typed actor client should support a polymorphic response. The response json should include a type discriminator property to allow for polymorphic deserialization by the actor client. The weakly-typed actor client must polymorphically deserialize the response when invoking
InvokeMethodAsync<ResponseBase>
on the weakly-typed actor client. This should yield aDerivedResponse
instance. Note that invokingInvokeMethodAsync<DerivedResponse>
is not polymorphic deserialization.While System.Text.Json support polymorphic deserialization from .NET 7, the Dapr .NET Actors SDK only builds .NET 6 and .NET 8, but not .NET 7. The E2E tests on the other hand do still build .NET 6, .NET 7 and .NET 8. As a consequence the .NET 7 build of the E2E tests uses the .NET 6 build of the .NET Actors SDK and does not run the polymorphic response test. Instead it runs a non-polymorphic test that directly deserializes to the derived class.
An operation on an actor invoked using a weakly-typed actor client should support a null response.
The problem was in the
ActorManager.DispatchWithoutRemotingAsync
method that serializes the response usingresult.GetType()
. This throws a null reference exception when the result is null. To support polymorphic deserialization in .NET 7 or later the serializer should use the declared return type on the interface instead of the runtime type.Closes #1213