Returning camelCase JSON Serialized by JSON.NET from ASP.NET MVC Controller Methods

Nov 25, 2025 · Programming · 10 views · 7.8

Keywords: ASP.NET MVC | JSON.NET | camelCase serialization | custom ActionResult | JSON formatters

Abstract: This article provides a comprehensive guide on returning camelCase formatted JSON data from ASP.NET MVC controller methods using JSON.NET. It analyzes the default PascalCase serialization issue and presents two main solutions: creating a custom JsonCamelCaseResult ActionResult and directly configuring JsonSerializerSettings. The content extends to ASP.NET Core concepts of multiple JSON serialization settings, demonstrating how custom formatters enable flexible JSON output control. Covering core code implementation, configuration methods, and practical scenarios, it offers complete technical guidance for developers.

Problem Background and Requirements Analysis

In ASP.NET MVC development, JSON data serialization is a common requirement. By default, the JSON.NET library serializes C# object properties using PascalCase naming convention. For example, for a Person class with FirstName and LastName properties, the serialization result is:

{
  "FirstName": "Joe",
  "LastName": "Public"
}

However, many frontend frameworks and the JavaScript community prefer camelCase naming convention. Developers want to transform the above JSON into:

{
  "firstName": "Joe",
  "lastName": "Public"
}

This requirement stems from standardization needs in frontend-backend collaboration, where camelCase is more natural and consistent in JavaScript environments.

Core Solution: Custom JsonCamelCaseResult

The most elegant solution is to create a custom ActionResult subclass specifically designed for camelCase JSON serialization. This approach encapsulates the serialization logic, keeping controller code clean.

First, define the JsonCamelCaseResult class:

public class JsonCamelCaseResult : ActionResult
{
    public JsonCamelCaseResult(object data, JsonRequestBehavior jsonRequestBehavior)
    {
        Data = data;
        JsonRequestBehavior = jsonRequestBehavior;
    }

    public Encoding ContentEncoding { get; set; }
    public string ContentType { get; set; }
    public object Data { get; set; }
    public JsonRequestBehavior JsonRequestBehavior { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        
        if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && 
            String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
        }

        var response = context.HttpContext.Response;
        response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
        
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        
        if (Data == null)
            return;

        var jsonSerializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        response.Write(JsonConvert.SerializeObject(Data, jsonSerializerSettings));
    }
}

Key aspects of this class include:

Usage Example in Controller

In MVC controllers, the custom JsonCamelCaseResult can be used similarly to standard JsonResult:

public class PersonController : Controller
{
    public ActionResult GetPerson()
    {
        var person = new Person 
        { 
            FirstName = "Joe", 
            LastName = "Public" 
        };
        
        return new JsonCamelCaseResult(person, JsonRequestBehavior.AllowGet);
    }
}

This approach provides clear separation of concerns, where controllers focus on business logic while serialization details are handled by JsonCamelCaseResult.

Alternative Approach: Direct Serialization Configuration

Besides custom ActionResult, serialization settings can be configured directly in controllers:

public ActionResult GetPersonDirect()
{
    var person = new Person { FirstName = "Joe", LastName = "Public" };
    
    var settings = new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver()
    };
    
    return new ContentResult
    {
        ContentType = "application/json",
        Content = JsonConvert.SerializeObject(person, settings),
        ContentEncoding = Encoding.UTF8
    };
}

This method is more direct but lacks the encapsulation and reusability of JsonCamelCaseResult.

Extension to ASP.NET Core Multi-Format Support

In ASP.NET Core, JSON serialization requirements can be more complex. The reference article discusses supporting mixed usage scenarios of multiple JSON formats (e.g., camelCase, PascalCase, snake_case).

The core idea involves custom input and output formatters combined with endpoint metadata for format selection:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class JsonSettingsNameAttribute : Attribute
{
    public JsonSettingsNameAttribute(string name)
    {
        Name = name;
    }
    public string Name { get; }
}

By adding [JsonSettingsName("camelCase")] attributes to controllers or action methods, specific serialization settings can be designated for those endpoints.

Implementing Custom Formatters

Custom formatters inherit from system default JSON formatters, overriding selection logic:

public class SpecificSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter
{
    public SpecificSystemTextJsonOutputFormatter(string settingsName, JsonSerializerOptions jsonSerializerOptions) 
        : base(jsonSerializerOptions)
    {
        SettingsName = settingsName;
    }

    public string SettingsName { get; }

    public override bool CanWriteResult(OutputFormatterCanWriteContext context)
    {
        if (context.HttpContext.GetJsonSettingsName() != SettingsName)
            return false;
        return base.CanWriteResult(context);
    }
}

This design allows mixing different JSON naming conventions within the same application, providing flexibility for legacy system integration and API versioning.

Configuration and Registration

Registering custom formatters in ASP.NET Core:

services.AddControllers()
    .AddJsonOptions("camelCase", options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    });

Through IConfigureOptions<MvcOptions> implementation, formatters are inserted into the MVC options formatter collection.

Performance and Best Practices

When using CamelCasePropertyNamesContractResolver, consider:

The custom ActionResult approach is optimal in traditional ASP.NET MVC, while custom formatters provide a more modern solution in ASP.NET Core.

Conclusion

Returning camelCase JSON data is a common requirement in ASP.NET MVC development. By creating a custom JsonCamelCaseResult class, developers can elegantly address this issue while maintaining code clarity and maintainability. In more complex ASP.NET Core scenarios, custom formatters and named options offer powerful multi-format support capabilities. These techniques not only solve specific serialization problems but also demonstrate the extensibility and flexibility of the .NET framework.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.