sebnilsson.com | Liquid Development Is What I Do
Seb Nilsson

Serialize HtmlString & MvcHtmlString in JSON.NET

JSON

The HtmlString-class (and MvcHtmlString) that is and has been used in the ASP.NET-platform, including WebPages, since the introduction of ASP.NET MVC is basically just a wrapped string, that doesn't gets automatically HTML-encoded when used in Razor-views. Despite this fact, if you want to serialize or deserialize this object in JSON.NET it will come back as null.

To be able to serialize an object containing a property of a type inheriting from IHtmlString, like HtmlString and MvcHtmlString, to then, for instance, cache the serialized object, you need to implement your own Newtonsoft.Json.JsonConverter that handles the serialization and deserialization.

HtmlStringConverter : Newtonsoft.Json.JsonConverter

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

public override object ReadJson(
    JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    var value = reader.Value as string;
    // Specifically MvcHtmlString
    if (objectType == typeof(MvcHtmlString))
    {
        return new MvcHtmlString(value);
    }
    // Generally HtmlString
    if (objectType == typeof(HtmlString))
    {
        return new HtmlString(value);
    }

    // Fallback for other (future?) implementations of IHtmlString
    return Activator.CreateInstance(objectType, value);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var htmlString = value as HtmlString;
    if (htmlString == null)
    {
        return;
    }

    writer.WriteValue(htmlString.ToString());
}

You then have to register this Converter in your JsonSerializerSettings like this:

CurrentConverter.Converters.Add(new HtmlStringConverter());