I have a C# web api which I use to access an F# library. I have created a DU of the types I want to return and use pattern matching to choose which is return back to the c# controller.
In the C# controller how do I access the data of the type which is return from the function call to the F# library?
C# Controller
public HttpResponseMessage Post()
{
var _result = Authentication.GetAuthBehaviour();
//Access item1 of my tuple
var _HTTPStatusCode = (HttpStatusCode)_result.item1;
//Access item2 of my tuple
var _body = (HttpStatusCode)_result.item2;
return base.Request.CreateResponse(_HTTPStatusCode, _body);
}
F# Types
module Types =
[<JsonObject(MemberSerialization=MemberSerialization.OptOut)>]
[<CLIMutable>]
type ValidResponse = {
odata: string;
token: string;
}
[<JsonObject(MemberSerialization=MemberSerialization.OptOut)>]
[<CLIMutable>]
type ErrorResponse = {
code: string;
message: string;
url: string;
}
type AuthenticationResponse =
| Valid of int * ValidResponse
| Error of int * ErrorResponse
F# function
module Authentication =
open Newtonsoft.Json
let GetAuthBehaviour () =
let behaviour = GetBehaviour.Value.authentication
match behaviour.statusCode with
| 200 ->
let deserializedAuthenticationResponse = JsonConvert.DeserializeObject<Types.ValidResponse>(behaviour.body)
Types.Valid (behaviour.statusCode, deserializedAuthenticationResponse)
| _ ->
let deserializedAuthenticationResponse = JsonConvert.DeserializeObject<Types.ErrorResponse>(behaviour.body)
Types.Error (behaviour.statusCode, deserializedAuthenticationResponse)
F# Discriminated Unions are compiled as abstract classes, with each case being a derived nested class. From C#, you can access the cases by attempting to downcast the result from GetAuthBehaviour
:
public HttpResponseMessage Post()
{
var result = Authentication.GetAuthBehaviour();
var valid = result as Types.AuthenticationResponse.Valid;
if (valid != null)
{
int statusCode = valid.Item1;
Types.ValidResponse body = valid.Item2;
return this.CreateResponse(statusCode, body);
}
var error = result as Types.AuthenticationResponse.Error;
if (error != null)
{
int statusCode = error.Item1;
Types.ErrorResponse body = error.Item2;
return this.CreateResponse(statusCode, body);
}
throw new InvalidOperationException("...");
}
Notice that the C# compiler doesn't know that you've handled all the cases, so you'll need to supply a branch that handles the case where result
is neither Valid
nor Error
. Here, I've simply thrown an exception as an example, but in a Web API, it'd probably be more appropriate to return a 500
status code.
All that said, though, why even have the trouble of writing and maintaining the Controllers in C#? You can write an ASP.NET Web API purely in F#.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With