I am considering converting an existing JSON api from a hacker version of MVC3 to the latest version of MVC4 Web Api. The MVC3 implementation uses JSON.NET to do all the serialization, which will make the update enjoyable and smooth.
I am stuck in setting how the results of an action get serialized. For example, I want some actions to return only a few properties of selected objects, while others can do fairly deep serialization. In my current implementation, an action can add a bunch of serialization overrides by setting the appropriate parameters in the HttpContext . They are later JsonResult for custom serialization through a class derived from JsonResult . The main use of the JsonConverters add- JsonConverters is to manage and reduce the number of keys / values ββobtained after serialization, and change the parameters for serialization depending on the action (certain actions should return more object parameters than others).
A condensed controller example and a class controlling the json series in my current MVC3 implementation:
public class TestController : JsonController { public JsonResult Persons() { ControllerContext.HttpContext.Items[typeof(IEnumerable<JsonConverter>)] = new JsonConverter[] { new InterfaceExtractorJsonConverter<IPersonForList>(), new StringEnumConverter() }; ControllerContext.HttpContext.Items[typeof(IContractResolver)] = new SpecialCamelCasePropertyNamesContractResolver(); } } public class JsonNetResult : JsonResult { public override void ExecuteResult(ControllerContext context) { var response = context.HttpContext.Response; var additionalConverters = context.HttpContext.Items[typeof(IEnumerable<JsonConverter>)] as IEnumerable<JsonConverter> ?? Enumerable.Empty<JsonConverter>(); var contractResolver = context.HttpContext.Items[typeof(IContractResolver)] as IContractResolver ?? new JsonContractResolver(); var typeNameHandling = TypeNameHandling.None; if (context.HttpContext.Items.Contains(typeof(TypeNameHandling))) typeNameHandling = (TypeNameHandling)context.HttpContext.Items[typeof(TypeNameHandling)]; response.Write(JsonConvert.SerializeObject(Data, Formatting.Indented, new JsonSerializerSettings { ContractResolver = contractResolver, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, Converters = additionalConverters, TypeNameHandling = typeNameHandling })); } }
In Web Api, I see that I can get the Json formatter from the configuration and change the global serialization.
var config = new HttpSelfHostConfiguration("http://localhost:8080"); var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().Single(); jsonFormatter.SerializerSettings.ContractResolver = new SpecialCamelCasePropertyNamesContractResolver(); jsonFormatter.SerializerSettings.Converters = new[] { new InterfaceExtractorJsonConverter<ITesting>() };
However, I planned to control the serialization of actions on an individual basis (or per controller), adding some attributes to indicate which JsonConverter's use. Thus, I would like the Json serializer to find the appropriate attributes assigned to the called action / controller and change the serialization accordingly. I am not sure where and how to do it. Should I inherit from JsonMediaTypeFormatter and do something there? What other options do I have?
source share