ASP.NET Core – How to make the controllers use Newtonsoft

By default, ASP.NET Core uses System.Text.Json for JSON serialization.

If you want to use Newtonsoft instead, you can add the Microsoft.AspNetCore.Mvc.NewtonsoftJson nuget package, then call AddNewtonsoftJson() in Startup.ConfigureServices() like this:

public class Startup { //rest of class public void ConfigureServices(IServiceCollection services) { services.AddControllers().AddNewtonsoftJson(); //rest of method } }
Code language: C# (cs)

In this article, I’ll show how to configure the Newtonsoft serializer options.

Install the right nuget package

Microsoft packaged up Microsoft.AspNetCore.Mvc.NewtonsoftJson based on the framework version, so you can’t just install the latest package. You have to find the latest one for the framework version you’re using.

If you try to install the latest package, and you’re not on the framework version that it targets, then you’ll get an error:

Error NU1202 Package Microsoft.AspNetCore.Mvc.NewtonsoftJson 5.0.8 is not compatible with netcoreapp3.1

I’ve listed the latest packages (at the time of this writing) for each framework version below.

Note: All of these are using the Package Manager Console (View > Other Windows > Package Manager Console).

.NET 5

Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 5.0.8
Code language: PowerShell (powershell)

.NET Core 3.1

Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.1.17
Code language: PowerShell (powershell)

.NET Core 3.0

Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.0.3
Code language: PowerShell (powershell)

Configuring Newtonsoft in ASP.NET Core

When you’re using Newtonsoft directly, to customize serialization you have to pass in a JsonSerializerSettings object. When you’re using it with ASP.NET Core, you pass the JsonSerializerSettings object to a framework method. Internally, it’ll pass that settings object to Newtonsoft when it’s serializing / deserializing.

You can configure Newtonsoft at the service level and at the action level.

Service-level configuration

To configure Newtonsoft at the service level, use AddNewtonsoftJson() in Startup.ConfigureServices() like this:

using Newtonsoft.Json.Converters; public class Startup { //rest of class public void ConfigureServices(IServiceCollection services) { services.AddControllers() .AddNewtonsoftJson(jsonOptions => { jsonOptions.SerializerSettings.Converters.Add(new StringEnumConverter()); }); //rest of method } }
Code language: C# (cs)

In this example, it’s adding the StringEnumConverter. This makes Newtonsoft serialize / deserialize enums names instead of values.

This configuration applies to all controllers. When the framework needs to serialize a response object or deserialize a request with JSON, it’ll use the settings you provided.

Note: Newtonsoft deserializes enum values and names by default, but only serializes enum values by default. To make it serialize enum names, you have to make it use StringEnumConverter.

Action-level configuration

You can configure Newtonsoft at the action level for serialization (but not for deserialization). You can either pass back a JsonResult or directly call JsonConvert.SerializerObject().

I’d only recommend this approach as a last resort. If you need to customize serialization for the model type the controller is dealing with, you may want to consider creating a custom converter instead (and doing service-level configuration).

Option 1 – Return JsonResult

When you return a JsonResult object, the framework will serialize the model object using the serializer settings you passed in. It will use the current serializer (System.Text.Json or Newtonsoft).

Here’s an example:

using Newtonsoft.Json; using System.Net; using Newtonsoft.Json.Converters; [HttpGet("{symbol}")] public async Task<IActionResult> Get(string symbol) { var stock = await GetStockFromRepo(symbol); var settings = new JsonSerializerSettings() { Converters = { new StringEnumConverter() } }; return new JsonResult(stock, settings) { StatusCode = (int)HttpStatusCode.OK }; }
Code language: C# (cs)

Notice that the settings parameter is of type object. This isn’t type safe, and can lead to a runtime exception. For example, if you have Newtonsoft configured, and you pass in a System.Text.Json.JsonSerializerOptions object, you’ll get this runtime exception:

System.InvalidOperationException: Property ‘JsonResult.SerializerSettings’ must be an instance of type ‘Newtonsoft.Json.JsonSerializerSettings’.

This means you have to know which serializer you’re using, which means it’s actually safer to directly call JsonConvert.SerializeObject().

Option 2 – Directly call JsonConvert.SerializeObject()

You always have the option of directly using Newtonsoft in the controller methods.

Here’s an example:

using Newtonsoft.Json; using System.Net; using Newtonsoft.Json.Converters; [HttpGet("{symbol}")] public async Task<IActionResult> Get(string symbol) { var stock = await GetStockFromRepo(symbol); var settings = new JsonSerializerSettings() { Converters = { new StringEnumConverter() } }; return new ContentResult() { StatusCode = (int)HttpStatusCode.OK, ContentType = "application/json", Content = JsonConvert.SerializeObject(stock, settings) }; }
Code language: C# (cs)

Note: If you use this approach, be sure to explicitly set the ContentType to application/json. This makes this option quite tedious.

Leave a Comment