AmoebaMan17
AmoebaMan17

Reputation: 742

Custom JsonConverter not working on WebAPI object deserialization

I have a model object that I send to the browser and gets sent back to me. I want that ID value in that object to be encrypted. I created a custom JsonConverter to encrypt the string and then decrypt it.

public class SecretItem
{
    [JsonConverter(typeof(EncryptedIdConverter))]
    public string Id { get; set; }
    public string Name { get; set; }
}

This is my EncryptedIdConverter class

class EncryptedIdConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        string encryptedValue = (string)value;

        if (!string.IsNullOrWhiteSpace(encryptedValue))
            encryptedValue = Encryption.EncryptString(encryptedValue);

        serializer.Serialize(writer, encryptedValue);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string decryptedString = (string)reader.Value;

        if (!string.IsNullOrWhiteSpace(decryptedString))
            decryptedString = Encryption.DecryptString(decryptedString);

        return decryptedString;
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(string).IsAssignableFrom(objectType);
    }
}

If I try calling the JsonConvert.Serialization functions, everything works correctly.

JsonConvert.SerializeObject(secretItem)
JsonConvert.DeserializeObject<SecretItem>([JSON secretItem]);

When I return the HttpActionResult Ok(secretItem)... the browser also gets the encrypted Id string.

However, when I POST the data back to my controller, my webapi method is not getting a decrypted property. It skips the JsonConverter.

public async Task<IHttpActionResult> Post(SecretItem secretItem)
{
    // Not decrypted
    var decryptedId = secretItem.Id;
}

Why would the deserialize logic not be working the same as the serialize logic in my WebAPI? I don't even know where to start debugging that.

We are using Newtonsoft.Json 10.0.0.0, MVC5, .NET Framework 4.6.1.

Upvotes: 5

Views: 5682

Answers (2)

Mohamed Elrashid
Mohamed Elrashid

Reputation: 8599

How is your Global.asax

protected void Application_Start()
{
  AreaRegistration.RegisterAllAreas();
  GlobalConfiguration.Configure(WebApiConfig.Register);
  FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  RouteConfig.RegisterRoutes(RouteTable.Routes);
  BundleConfig.RegisterBundles(BundleTable.Bundles);
}

it should work

maybe you need a TypeConverter

Model binding

When Web API calls a method on a controller, it must set values for the parameters, a process called binding

  • This is called Model binding

     Post(SecretItem secretItem)
    
  • Model binding use a TypeConverter

JSON Serialization

  • This is called JSON Serialization

    HttpActionResult Ok(secretItem)
    
  • JSON Serialization use a JsonConverter

Documentation

more

Upvotes: 2

AmoebaMan17
AmoebaMan17

Reputation: 742

It turns out the code is working correctly. The problem was that on the POST that was being tested, the content-type wasn't set to "application/json". So, it didn't use the JsonNetFormatter and therefore skipped the converter.

Once I set the contentType, everything works!

Upvotes: 4

Related Questions