Configure ASP Web API API serialization to invoke an action

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?

+6
source share
1 answer

I have never seen anyone want to control serialization this way. But to achieve your goal with minimal refinement, I would return all this information from your method directly:

 class JsonNetResponse { public IContractResolver ContractResolver { get;set; } // Other Json.Net bits public object Value { get; set; } } 

Then I would create a custom Formatter, with which I could process these objects:

 class JsonNetFormatter : MediaTypeFormatter { public override bool CanWriteType(Type t) { return typeof(JsonNetResponse).IsAssignableFrom(t); } // TODO WriteToStreamAsync which is basically a copy of your original JsonNetResult } 
+2
source

Source: https://habr.com/ru/post/921840/


All Articles