2 Array functions in F# I can never remember

Array.sub

Builds a new array that contains the given subrange specified by starting index and length.

// Signature:
Array.sub : 'T [] -> int -> int -> 'T []

// Usage:
Array.sub array startIndex count

Array.blit

Reads a range of elements from the first array and writes them into the second.

// Signature:
Array.blit : 'T [] -> int -> 'T [] -> int -> int -> unit

// Usage:
Array.blit source sourceIndex target targetIndex count

F# Record Serialization in ASP.NET Web API

It’s very easy to get started on an F# Web API application thanks to Dan Mohl‘s excellent F# C# MVC 4 template. After installing the template, create an F# and C# Web Application (ASP.NET MVC 4) in Templates .. Visual F# .. ASPNET and select WebApi Project in the next dialog. You start with 2 projects, a C# MVC 4 project (WebApi) and an F# Web API project (WebAppApi)

If you look in the ValuesController.cs in the WebAppApi project, you’ll see the following code:

namespace FsWeb.Controllers

open System.Web
open System.Web.Mvc
open System.Net.Http
open System.Web.Http

type ValuesController() =
    inherit ApiController()

    // GET /api/values
    member x.Get() = [| "value1"; "value2" |] |> Array.toSeq
    // GET /api/values/5
    member x.Get (id:int) = "value"
    // POST /api/values
    member x.Post ([<FromBody>] value:string) = ()
    // PUT /api/values/5
    member x.Put (id:int) ([<FromBody>] value:string) = ()
    // DELETE /api/values/5
    member x.Delete (id:int) = ()

To test this you can run this project and test the API using Fiddler, or alternatively you can follow Scott Hanselman’s post on installing HTTPie. (Replace [port] with whatever is configured for your application.)

C:\>http http://localhost:port/api/values
HTTP/1.1 200 OK
Content-Length: 19
Content-Type: application/json; charset=utf-8
Date: Tue, 09 Oct 2012 21:50:53 GMT
Server: Microsoft-IIS/8.0

[
    "value1",
    "value2"
]

Let’s try something more complex. Say our model is a record:

type Value = { Id: int; Name: string; }

(Admittedly it’s not that complex but it will suit our purpose.)

Now change the Get() method on the ValuesController

member x.Get() = [|
    { Id=1; Name="value1" };
    { Id=2; Name="value2" } |] |> Array.toSeq

Running HTTPie as before, we get the following JSON output:

C:\>http http://localhost:port/api/values
HTTP/1.1 200 OK
Content-Length: 55
Content-Type: application/json; charset=utf-8
Date: Tue, 09 Oct 2012 22:54:52 GMT
Server: Microsoft-IIS/8.0

[ 
    {
        "Id@": 1, 
        "Name@": "value1" 
    }, 
    { 
        "Id@": 2,
        "Name@": "value2" 
    } 
]

Unfortunately the result is not exactly how we want it. What’s happening is that JSON.NET is serializing the field names of the record rather than the properties, hence the @ signs at the end of each member. To fix this, we can add a reference to the Newtonsoft.JSON nuget package in the WebAppApi project, and mark the record with a JsonObject attribute

open Newtonsoft.Json

[<CLIMutable>]
[<JsonObject(MemberSerialization=MemberSerialization.OptOut)>]
type Value = { Id: int; Name: string; }

Now calling the API again, we get the following JSON response

[
    {
        "Id": 1,
        "Name": "value1"
    },
    {
        "Id": 2,
        "Name": "value2"
    }
]

If you only ever intend your clients to use JSON to talk to your API you could consider yourself done. But what does the response look like as XML?

C:\>http http://localhost:port/api/values Accept:application/xml
HTTP/1.1 200 OK
Content-Length: 291
Content-Type: application/xml; charset=utf-8
Date: Wed, 10 Oct 2012 22:44:22 GMT
Server: Microsoft-IIS/8.0

<ArrayOfValue 
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://schemas.datacontract.org/2004/07/FsWeb.Controllers">
    <Value>
        <Id_x0040_>1</Id_x0040_>
        <Name_x0040_>value1</Name_x0040_>
    </Value>
    <Value>
        <Id_x0040_>2</Id_x0040_>
        <Name_x0040_>value2</Name_x0040_>
    </Value>
</ArrayOfValue>

To serialize correctly as both XML and Json we can use the DataContract attribute (in System.Runtime.Serialization.dll)

open System.Runtime.Serialization

[<CLIMutable>]
[<DataContract>]
type Value = { 
    [<DataMember>]Id: int; 
    [<DataMember>]Name: string; }

Now our response looks better:

<ArrayOfValue 
    xmlns="http://schemas.datacontract.org/2004/07/FsWeb.Controllers" 
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Value>
        <Id>1</Id>
        <Name>value1</Name>
    </Value>
    <Value>
        <Id>2</Id>
        <Name>value2</Name>
    </Value>
</ArrayOfValue>

Unfortunately this technique requires us to decorate each and every field with the DataMember attibute. I’m sure there must be a better way.