Unplanned
Last Updated: 24 Nov 2023 11:31 by ADMIN
Azhar
Created on: 11 Feb 2021 11:03
Type: Feature Request
59
Migrate to System.Text.Json for serialization, instead of using Newtonsoft.Json

I have projects on .NET Core and I want to use the System.Text.Json serializer that is the new default, but reporting relies on Newtonsoft.Json.

---

ADMIN EDIT

There are two approaches that can be taken right now to solve this:

OPTION 1: define separate endpoints (services, projects) for the different tasks - they can still use the same database layer through a shared project, depending on the architecture you have. This would let you have separated services with the appropriate serializers without custom attributes and code (see below). For example, create a separate project for the reporting REST services.

OPTION 2: add some custom decoration on the endpoints so you can choose which serializer is used on each, you can find some examples here: https://stackoverflow.com/questions/59650907/how-to-configure-two-json-serializers-and-select-the-correct-one-based-on-the-ro - the point being to register a serializer depending on the endpoint based on your own code rather than let the framework put one in for all endpoints.

NOTE: This would be a breaking change.

---

7 comments
ADMIN
Todor
Posted on: 24 Nov 2023 11:31

Hi Thomas,

The code shared by Dominik works as expected. I think it is fine to apply the approach in your Reporting projects.

We need to discuss the implementation within the team and decide whether we may recommend it to our users. We will follow up in the thread when we have something to share.

Regards,
Todor
Progress Telerik

Stay tuned by visiting our roadmap and feedback portal pages, enjoy a smooth take-off with our Getting Started resources, or visit the free self-paced technical training at https://learn.telerik.com/.
Thomas
Posted on: 17 Nov 2023 21:56

Domink:
Thanks for the solution, it works like a charm.  

 

@Momchil can you guys take a look at Dominics solution and see if its feasible to integrate into the solution.  I completely agree that adding the two serialization engines to the service container is a bad idea.  No matter the order, .Net 8 seems to want to use Newtonsoft instead of System.Text.Json which is the opposite of what we want.

ADMIN
Momchil
Posted on: 18 Oct 2023 14:43

Hello Dominik,

Thank you for pointing out the issue with our demos.

I looked into it and found that after the R3 2023 release, all HTML5 integration demos now target .NET 6 so keep in mind that the .NET 7 demo is affected as well.

This is why I have logged a bug item on your behalf and added your vote to it. I am also updating your account's Telerik Points as a token of gratitude.

Best Regards,
Momchil
Progress Telerik

Stay tuned by visiting our roadmap and feedback portal pages, enjoy a smooth take-off with our Getting Started resources, or visit the free self-paced technical training at https://learn.telerik.com/.
Dominik
Posted on: 17 Oct 2023 20:38

I have attached a working sample based on "Progress\Telerik Reporting R3 2023\Examples\CSharp\.NET 8\Html5IntegrationDemo"

What I changed:
- Added 
--ToNewtonSoftActionFilter, NewtonSoftJsonModelBinder, ValidateModelStateAttribute
--ReportDesignerControllerSTJBase, ReportsControllerSTJBase
- Program.cs
-- Removed AddNewtonsoftJson
-- Added "builder.Services.AddSingleton<ToNewtonSoftActionFilter>();"
- ReportDesignerController and ReportsController use the new base classes

@Telerik You might want to update your NET8 sample. It still points to NET6.

Gabriel
Posted on: 17 Oct 2023 11:59

I'd be very interested in your solution. Could you post a complete example?

 

Thank you.

Dominik
Posted on: 14 Oct 2023 19:55

I didn't like either option. So I've made a modification to the second one.

I didn't like the first because that would mean too much overhead and I really wanted to avoid adding NewtonsoftJson to the service container. The two aren't really mean to coexist and the hack may break on any change on either package.

So instead of using a "MySuperJsonInputFormatter" which I also dislike because of its global nature, I did the following:
I created a wrapper Controller for 
ReportDesignerControllerBase and ReportsControllerBase which has a ServiceFilterAttribute attached to it which will take the result object of any endpoint, use the newtonsoft serializer to produce a json string and replace the endpoint result with that. The request parameters which are classes have a ModelBinderAttribute attached which will cause the objects to be deserialized by newtonsoft.

Example:

[ServiceFilter(typeof(ToNewtonSoftActionFilter))]
public class ReportsControllerSTJBase : ReportsControllerBase {

...

[HttpPost("clients/{clientID}/instances/{instanceID}/documents", Order = -1)]
public virtual new IActionResult CreateDocument(string? clientID, string? instanceID, [FromBody][ModelBinder(typeof(NewtonSoftJsonModelBinder))] CreateDocumentArgs args) => base.CreateDocument(clientID, instanceID, args);

...

}

With this I only need to add the NewtonSoft package but the usage is completely confined to the two controllers. No ".AddNewtonsoftJson" or any global Formatters. And I haven't had any problems since I started using it many month ago.

To make this work less tedious, I've automated the creation (by using reflection) to create those wrapper classes.

 

Now here is my question:
I'd much rather not have to create those wrapper classes myself, instead it would be awesome if this or something like it was already contained in the package, for various reasons. So would it be possible to include something like that?

If interested I could clean up the code a bit more and post it here.

kdubious
Posted on: 08 Dec 2022 14:13

>> NOTE: This would be a breaking change.

Understood. But without this fix, one cannot use Kendo and Telerik Reporting in the same .NET6 app.