Record Types and Serialization -> F# to C#
February 3, 2015 1 Comment
I was working on an exercise where I have a F# component being consumed by an MVC web application written in C#. As I already asked about here, the CLIMutable is a great feature to the F# language spec. I created a basic record type with the CLIMutable attribute like so:
1 [<CLIMutable>] 2 type Account = {Number:int; Holder:string; Amount:float}
I then create an instance of that type in the controller written in C#:
1 public class AccountController : ApiController 2 { 3 [HttpGet] 4 public Account Index() 5 { 6 var account = new Account(); 7 account.Amount = 100; 8 account.Holder = "Homer"; 9 account.Number = 1; 10 return account; 11 } 12 }
When I write the site and call the method via Fiddler, I get a nasty “@” symbol added to the end of the name:
which is no good. I then thought of my question on SO and Mark Seeman’s blog post on this topic found here. I added this to the WebApiConfig class
1 public static void Register(HttpConfiguration config) 2 { 3 // Web API configuration and services 4 GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = 5 new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); 6 7 // Web API routes 8 config.MapHttpAttributeRoutes(); 9 10 config.Routes.MapHttpRoute( 11 name: "DefaultApi", 12 routeTemplate: "api/{controller}/{id}", 13 defaults: new { id = RouteParameter.Optional } 14 ); 15 }
And the “@” symbol goes away
The next task was to add in option types. I updated the class like so:
1 [<CLIMutable>] 2 type Account = {Number:int;Holder:string option;Amount:float}
I then added a F# class to do the assignment of the value
1 type AccountRepository() = 2 member this.GetAccount() = 3 {Number=1;Holder=Some "Homer"; Amount=100.}
And then updated the controller:
1 [HttpGet] 2 public Account Index() 3 { 4 AccountRepository repository = new AccountRepository(); 5 return repository.GetAccount(); 6 }
And I get this:
Which is not what my UI friends want. They want the same value for the json –> they want to ignore the existence of the option type. Fair enough. I hit up stack overflow here and Sven had a great answer pointing me to Isaac Abraham’s serializer found here. I popped that puppy into the project and updated the WebApiConfig like so:
1 var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter; 2 formatter.SerializerSettings.ContractResolver = new DefaultContractResolver(); 3 formatter.SerializerSettings.Converters.Add(new IdiomaticDuConverter());
And boom goes the dynamite.
Pingback: F# Weekly #6, 2015 | Sergey Tihon's Blog