Yes, they are both ServiceStack endpoints. Your statement is true, it really can parse both MS WCF format and ISO8601, my fault for not realizing this. So if the server doesn’t override the serialization or deserialization function and is not forcing client to use some specific formats, which ServiceStack cannot recognize, everything works fine.
But I wanted to focus my question at some cases, where it doesn’t work this way and it may become a problem.
Let’s say, Endpoint1 doesn’t override serialization/deserialization functions at all and uses only default JsConfig
values.
Endpoint2 overrides some configurations and serialization/deserialization functions in JsConfig
and JsConfig<T>
, e.g. it uses
JsConfig.IncludeNullValues = true;
and has setup some “crazy” outbound serialization like:
JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString("yyyy MMMM dd", CultureInfo.CurrentCulture);
JsConfig<DateTime?>.SerializeFn = time => time.HasValue ? new DateTime(time.Value.Ticks, DateTimeKind.Local).ToString("yyyy MMMM dd", CultureInfo.CurrentCulture) : null;
I created two identical test services on each endpoint (in my local debug environment) to demonstrate:
public class TestData
{
public DateTime DateTimeNow { get; set; } = DateTime.Now;
public DateTime? DateTimeNowNullable { get; set; } = DateTime.Now;
public DateTime? DateTimeNowNullableNull { get; set; } = null;
}
[Route("/api/test", "GET")]
public class GetTestData : IReturn<GetTestDataResponse> {}
public class GetTestDataResponse
{
public TestData TestData { get; set; }
}
public class TestService : Service
{
public GetTestDataResponse Get(GetTestData getTestData)
{
return new GetTestDataResponse()
{
TestData = new TestData()
};
}
}
Endpoint 1 response:
Endpoint 2 response:
I have generated 2 DTOs (through x csharp
tool), one with global namespace Endpoint1, second with global namespace Endpoint2.
Now I create 2 clients:
var endpoint1Client = new JsonServiceClient("http://localhost:8001");
var endpoint2Client = new JsonServiceClient("http://localhost:8002");
and call get:
var testDataResponse1 = endpoint1Client.Get(new Endpoint1.GetTestData());
var testDataResponse2 = endpoint2Client.Get(new Endpoint2.GetTestData());
The resulting deserialized data looks like this - Endpoint2 sends Date in format, that is not recognized and cannot be parsed.
The obvious solution would be to use JsConfig to override deserialization from unrecognized format on client side:
JsConfig<DateTime>.DeSerializeFn = time => DateTime.TryParseExact(time, "yyyy MMMM dd", CultureInfo.CurrentCulture, DateTimeStyles.None, out var parsedDate) ? parsedDate : default;
JsConfig<DateTime?>.DeSerializeFn = time => time != null && DateTime.TryParseExact(time, "yyyy MMMM dd", CultureInfo.CurrentCulture, DateTimeStyles.None, out var parsedDate) ? parsedDate : null;
but as expected, now the problem just swaps, since this deserialization is also applied to the Endpoint1 calls:
I am basically looking for a non-static way to configure JsonServiceClient with some ServiceStack.Text JsConfig, that only applies to that specific JsonServiceClient instance and does not affect anything outside of it, without need of using scopes or anything, that must be exhaustively used at each specific call. Initialized only once e.g. in JsonServiceClient constructor, and automatically applied by default at each internal use of serialization/deserialization.
This may also be usefull for OrmLite, since one may want to save/retrieve serialized data in specific formats, but not to use these formats outside of database calls.