Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
51cb8ab
messagepack format "POC"
Daniel-Svensson May 26, 2026
5547219
Add Filtered Type Shape provider for choosing which properties to ser…
Daniel-Svensson May 26, 2026
544901c
Initial plan
Copilot May 31, 2026
b367f17
Add initial MessagePack wire-format support
Copilot May 31, 2026
40186f1
Setup tests to use messagepack for .net 10
Daniel-Svensson May 31, 2026
a47493b
Merge branch 'msgpack' into copilot/msgpack
Daniel-Svensson May 31, 2026
c87adeb
Address MessagePack review feedback
Copilot May 31, 2026
ab7ce22
Add async MessagePack method parameter converter
Copilot May 31, 2026
278e896
Use filtered provider for MessagePack parameter converters
Copilot May 31, 2026
993c1d7
remove comment
Daniel-Svensson Jun 1, 2026
fd65f82
som minor restructuring
Daniel-Svensson Jun 1, 2026
caf5599
Som updates to filtered type shape
Daniel-Svensson Jun 1, 2026
a743b68
envelope changes
Daniel-Svensson Jun 1, 2026
440ce2c
add code for manual envelope handling
Daniel-Svensson Jun 1, 2026
9c3f5ae
various fixes and refactoring
Daniel-Svensson Jun 1, 2026
1492584
Fix invoke parameters
Daniel-Svensson Jun 1, 2026
68ddc4c
wip
Daniel-Svensson Jun 1, 2026
acf5675
workaround for KnownType not beeing honored
Daniel-Svensson Jun 1, 2026
c7712be
Add hack to get Nerdbank.MessagePack.IMessagePackSerializationCallbac…
Daniel-Svensson Jun 1, 2026
28794ff
add object derived type mapping for changeset (on server)
Daniel-Svensson Jun 1, 2026
8e810f9
WIP, add ai generated converter for changesetentry on server
Daniel-Svensson Jun 2, 2026
c80da55
Fix invoke returning void
Daniel-Svensson Jun 5, 2026
8ee0eec
only test invoke
Daniel-Svensson Jun 5, 2026
6b878b8
Add IMessagePackSerializationCallbacks to complex object
Daniel-Svensson Jun 5, 2026
eb380d6
Fix all but 1 invoke tests
Daniel-Svensson Jun 5, 2026
11f58e7
Use surrogate types for serialization of entitites
Daniel-Svensson Jun 6, 2026
b686dc3
Fix query return inheritance with surrogate types
Daniel-Svensson Jun 6, 2026
238f10d
Only emit type info if there are derived types (Invoke+Query works)
Daniel-Svensson Jun 7, 2026
73305f2
Fix included entities on client
Daniel-Svensson Jun 7, 2026
cdd53c8
fix problem with unions
Daniel-Svensson Jun 7, 2026
3bbfad0
use null for base type
Daniel-Svensson Jun 7, 2026
fb6a84d
Fix deserialization of class hierarhies for Included entities
Daniel-Svensson Jun 7, 2026
c416e23
queries is working
Daniel-Svensson Jun 8, 2026
bbcd250
Initial changeset working
Daniel-Svensson Jun 12, 2026
c67d210
FIx most of submit test failures with a working ObjectConverter on cl…
Daniel-Svensson Jun 14, 2026
e67281d
Better client error for invalid entity actions
Daniel-Svensson Jun 14, 2026
ca8a4d7
Update serialization provider abstraction
Daniel-Svensson Jun 14, 2026
d526d08
Add fallback for when TryReadStringSpan fails
Daniel-Svensson Jun 14, 2026
8abd907
Fix MetaMember lookup in filtered typeshape provider
Daniel-Svensson Jun 14, 2026
30f8987
Improve discriminator logic
Daniel-Svensson Jun 14, 2026
b456da2
fix void result again
Daniel-Svensson Jun 14, 2026
204f444
fix ArgumentException Throw helper usage
Daniel-Svensson Jun 14, 2026
b4105a7
serialize queryResults as base type
Daniel-Svensson Jun 14, 2026
c9c0741
Cleanup and optimize SurrogateFactory somewhat
Daniel-Svensson Jun 14, 2026
6bad68a
Update codegen to emit deserialization constructor
Daniel-Svensson Jun 14, 2026
ce8331e
update generated code for T4 templates
Daniel-Svensson Jun 14, 2026
5782ea4
fix parameter name
Daniel-Svensson Jun 14, 2026
ffc399b
update nuspec with dependencies
Daniel-Svensson Jun 14, 2026
3879fcf
remove BinaryConverter
Daniel-Svensson Jun 14, 2026
a600a93
remove extra objectconverter on client
Daniel-Svensson Jun 14, 2026
eb5ba8f
Fixa aspnetcore tests
Daniel-Svensson Jun 15, 2026
032c15c
Revert "remove BinaryConverter"
Daniel-Svensson Jun 15, 2026
db9a6c6
Fix coderabbiy comments
Daniel-Svensson Jun 15, 2026
03ade9f
fix a number of coderabbit review comments
Daniel-Svensson Jun 15, 2026
758ccc1
Merge branch 'main' of https://github.com/OpenRIAServices/OpenRiaServ…
Daniel-Svensson Jun 15, 2026
47e978f
run webserver using net10 on local development
Daniel-Svensson Jun 15, 2026
cdafedf
fix exception test case
Daniel-Svensson Jun 15, 2026
03ef477
Apply suggestions from code review
Daniel-Svensson Jun 15, 2026
9de3d9f
remove type shape provider for now
Daniel-Svensson Jun 15, 2026
cd47f76
sync version of System.IO.Hashing
Daniel-Svensson Jun 15, 2026
ec041d9
Fix some comments, including fixing discriminator for DervicedTypeShape
Daniel-Svensson Jun 15, 2026
1c2fd79
update error handling for T4 templates
Daniel-Svensson Jun 15, 2026
df6c5e5
Fix last coderabbit comments
Daniel-Svensson Jun 15, 2026
2e4706a
fix review comments
Daniel-Svensson Jun 15, 2026
9698dbf
update aspnetcore nuget version
Daniel-Svensson Jun 15, 2026
9499e5b
FIx handling of inheritance for entities
Daniel-Svensson Jun 16, 2026
4b1746a
Apply suggestions from code review
Daniel-Svensson Jun 16, 2026
f123b70
Apply suggestions from code review
Daniel-Svensson Jun 16, 2026
ac3a7f8
Fix sonarcloud warnings
Daniel-Svensson Jun 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ CI separates test execution by target framework and excludes `OpenRiaServices.Co
- Follow `.editorconfig` and existing style in nearby files.
- C# uses 4-space indentation and C# 14.0 (`src\Directory.Build.props`).
- Framework projects enable recommended analysis mode and XML documentation generation.
- New public, protected, and internal APIs should have XML documentation comments.
- New public, protected, and internal APIs should have XML documentation comments, this is not required for assembly local ("private") types.
- Release builds should not introduce warnings.
- Assembly signing is enabled centrally in `src\Directory.Build.props`; framework and test projects use keys from `src\snk`.
- Use existing libraries and patterns. Do not modernize unrelated legacy code while fixing a targeted issue.
Expand Down
15 changes: 12 additions & 3 deletions NuGet/OpenRiaServices.Client.Core.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@
<language>en-US</language>
<tags>WCF RIA Services RIAServices Silverlight OpenRiaServices</tags>
<dependencies>
<group targetFramework="net472" />
<group targetFramework="net8.0" />
<group targetFramework="net8.0-windows7.0" />
<group targetFramework="net472">
<dependency id="Nerdbank.MessagePack" version="1.2.4" exclude="Build,Analyzers" />
<dependency id="System.IO.Hashing" version="10.0.9" exclude="Build,Analyzers" />
</group>
<group targetFramework="net8.0">
<dependency id="Nerdbank.MessagePack" version="1.2.4" exclude="Build,Analyzers" />
<dependency id="System.IO.Hashing" version="10.0.9" exclude="Build,Analyzers" />
</group>
<group targetFramework="net8.0-windows7.0">
<dependency id="Nerdbank.MessagePack" version="1.2.4" exclude="Build,Analyzers" />
<dependency id="System.IO.Hashing" version="10.0.9" exclude="Build,Analyzers" />
</group>
Comment thread
Daniel-Svensson marked this conversation as resolved.
</dependencies>
<frameworkReferences>
<group targetFramework="net8.0-windows7.0">
Expand Down
29 changes: 29 additions & 0 deletions docs/messagepack-serialization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# MessagePack serialization wire schema (draft)

OpenRiaServices supports MessagePack with MIME type `application/vnd.msgpack`.

## Request envelope (POST/QUERY/Submit)

Top-level object map:

- `Parameters`: map<string, value?>
Parameter name to a MessagePack value serialized with the declared parameter type converter. `nil` means `null`.
- `QueryOptions`: array of `ServiceQueryPart` (optional)
- `IncludeTotalCount`: bool (optional)

## Success response envelope

Top-level object map:

- `Result`: value?
MessagePack value for the declared operation return type. `nil` means `null` / no value.

## Fault response envelope

Top-level object map:

- `Fault`: `DomainServiceFault`
## Notes

- GET query behavior stays unchanged (URL-encoded query parameters).
- Envelopes are map-based for schema/version tolerance.
73 changes: 73 additions & 0 deletions src/MessagePackWorkarounds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Serialization Of Class hierarchies does not work

Consider the following class hierarchy.
Where A is annotated with `KnownTypeAttribute` for `B` and `C`.
```
A -> B -> C
```

A serializer for A can properly serialize and deserialize all 3 classes.
A serializer for B does not work for objects of type `C`.

Desired behaviour:
* Serializer for `A` can serialize/deserialize all 3 types (with a single discriminator)
* Serializer for `B` can serialize/deserialize B and C
* Can serialize/deserialize objects of known type based on "object" serializer
* Should work with existing code gen (basetype has all "known type" attribytes)
* No usage of surrogates/marshalling types

Problems:
* Using DerivedShapeMapping have the following issues
* Serialization of B using shape A suddenly use 2 discriminators `["B", ["B", ...] ]`
* Serialization of B`s derived classses does not pick the most specific instance , a bug??
* There is some sorting of DerivedShapeMapping based on inheritance,
but it can still pick the base instance instead of the actual type.
This is especially bad when B is abstract.
See `AI_Detail` class where derived types were serialized as `AI_Detail` insted of actual type.
* Cannot add custom converter for types using built in

Workarounds:
* Added a `ObjectConverter` class on client
* The `ObjectConverter` class has a custom "ReflectionTypeShapeProvider" with special assemblies specified
Also "unwrapping" of `IUnionTypeShape<T>` is needed to get the underlying "object serializer"
* This allows caching of the "ObjectSerializers"
* Added `SurrogateConverter` class on server
* Create dynamic classes/instances with same name and properties (without KnownTypeAttributes)
* To get Queries, Invoke and method parameters to work
* See test : Inherit_Run_CUD_Delete_Derived which failes since abstract class cannot be deserialized
* Maybe always serialize/deserialize using "base type" serializer ??
* MethodParametersConverter (Client)
* ChangeSetEntryConverter (Client) (entity actions)
* MessagePackHttpDomainClient.GetResponseEnvelopeType* (client)
* MethodParametersConverter (server)
* MessagePackRequestSerializer.WriteQueryResponseAsync (server)
* MessagePackRequestSerializer.CreateInvokeResponseEnvelope (server)


# Serializing using

# Object and Union converter for same type cannot coexist

Problems
* Cannot get "object" converter for a specific Type, the converter is "always" UnionTypeShape
* Converter Cache does dot distinguish betweeen `IUniontTypeShape<T>` and `IObjectTypeShape<T>`

# Other bugs

PolyType does not handle TestDomainServices.MockReport correctly, it generate a constructor takeing 6 arguments meaning
serialization callbacks will note be executed.

Resulting in failed test

* Addin a ctor with required parameters still does not resolve the issue.
* adding required parameters to ctor leads to duplicate parameters

# Other todos etc

* Creata a server side test corresponding to DomainClient_SubmitWithNonexistentDomainMethod
* Validate behaviour when client send entityAction that does not exist
* Update generated code to handle TestDomainServices.MockReport issue with required members
* Ensure whole class hierarchies are properly serialized/deserialized when using "object" serializer
* See " Maybe always serialize/deserialize using "base type" serializer ??" above
* PARTIALLY IMPLEMENTED (Queries only)
* `MessagePackHttpDomainClient.GetResponseEnvelopeType` + `MessagePackRequestSerializer.WriteQueryResponseAsync`
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ abstract class HttpDomainClient : DomainClient
private static readonly ConcurrentDictionary<(Type serviceInterface, string operationName), MethodParameters> s_methodParametersCache = new ConcurrentDictionary<(Type serviceInterface, string operationName), MethodParameters>();

private readonly OpenRiaServices.Client.DomainClients.HttpDomainClientFactory _factory;
private readonly Type _serviceInterface;

/// <inheritdoc/>
public override bool SupportsCancellation => true;

private protected HttpClient HttpClient { get; }
private protected Type ServiceInterface { get; }

private protected HttpDomainClient(HttpClient httpClient, Type serviceInterface, OpenRiaServices.Client.DomainClients.HttpDomainClientFactory factory)
{
Expand All @@ -40,7 +40,7 @@ private protected HttpDomainClient(HttpClient httpClient, Type serviceInterface,
ArgumentNullException.ThrowIfNull(factory);

HttpClient = httpClient;
_serviceInterface = serviceInterface;
ServiceInterface = serviceInterface;
_factory = factory;
}

Expand All @@ -50,7 +50,7 @@ private protected HttpDomainClient(HttpClient httpClient, Type serviceInterface,

private protected MethodParameters GetMethodParameters(string operationName)
{
return s_methodParametersCache.GetOrAdd((_serviceInterface, operationName), static key => new MethodParameters(key.serviceInterface, key.operationName));
return s_methodParametersCache.GetOrAdd((ServiceInterface, operationName), static key => new MethodParameters(key.serviceInterface, key.operationName));
}

private protected string GetParameterValueAsString(string operationName, string parameterName, object parameterValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace OpenRiaServices.Client.DomainClients.Http
/// <summary>
/// A dictionary of parameter name and types for a method
/// </summary>
internal class MethodParameters
internal sealed class MethodParameters
{
private readonly string _operationName;
private readonly Dictionary<string, Type> _parameterNameAndTypeDictionary;
Expand Down
Loading
Loading