3

My Custom Action Filter Attribute to convert a JSON response of MVC core webApi from "camelCase" to "pascalCase" is not working.

Tried using:

services.AddMvc()
    .AddJsonOptions(options => 
        options.SerializerSettings.ContractResolver = new DefaultContractResolver());

However, this kind of global setting changes all response to Pascal case. I want to change only a limited API response to Pascal case.

Custom ActionFilterAttribute:

public class CancelCamelCaseResolverConfigurationAttribute : ActionFilterAttribute
{

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        base.OnResultExecuted(context);

        var objectResult = context.Result as ObjectResult;
        if (objectResult != null)
        {
            objectResult.Formatters.Clear();
            objectResult.Formatters.Add(new JsonOutputFormatter(
                new JsonSerializerSettings()
                {
                    Formatting = Formatting.None,
                    ContractResolver = new DefaultContractResolver()
                }, ArrayPool<char>.Shared));
        }
    }
}

And use in the webApi controller:

[CancelCamelCaseResolverConfiguration]
public class FrmMainSearchController : AtlasApiController<FrmMainSearchController>
{
    /*Api*/
}

Expected result:

searchCriteria = [{Key: "xx", Value: "yy"}]

Actual result:

searchCriteria = [{key: "xx", value: "yy"}]
Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
Mahesh Sharp
  • 85
  • 1
  • 7

1 Answers1

4

You're almost there: You need override the OnActionExecuted() method instead of the OnResultExecuted().

It's too late to change the formatters when the OnResultExecuted() filter method is invoked.

How to fix:

Override the OnResultExecuted method so that the formatter is changed before the result execution:

public override void OnResultExecuted(ResultExecutedContext context)
public override void OnActionExecuted(ActionExecutedContext context)
{
    ...
}

As a side note, you didn't check for type JsonResult. To make it work with Json() or JsonResult(), you need check the result type dynamically:

public class CancelCamelCaseResolverConfigurationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        base.OnActionExecuted(context);
        switch(context.Result){
            case JsonResult j:
                var result = new ObjectResult(j.Value);
                context.Result = result;
                ChangeFormatting(result);
                break;
            case ObjectResult o:
                ChangeFormatting(o);
                break;
            default:
                return;
        }

    }

    private void ChangeFormatting(ObjectResult result){
        if (result == null){ return; }
        result.Formatters.Clear();
        result.Formatters.Add(new JsonOutputFormatter(
            new JsonSerializerSettings()
            {
                Formatting = Formatting.None,
                ContractResolver = new DefaultContractResolver()
            }, ArrayPool<char>.Shared)
        );
    }
}
itminus
  • 23,772
  • 2
  • 53
  • 88