I’m working on building a website using the F# MVC 5 template, and I noticed that the template creator uses formally declared types for the route defaults. In VB.Net and C#, this is typically done with anonymous classes, but these don’t exist in F# my current work around is to use an Expando Object, like this:
<code>[<RequireQualifiedAccess>]
module RouteConfig =
let private createDefaults (propValuePairs : seq<string * obj>) : obj =
let defaults = ExpandoObject() :> IDictionary<string,obj>
propValuePairs |> Seq.iter (fun (key,value) -> defaults.Add(key,value) )
box defaults
/// create a pair, boxing the second item
let inline private (=>) (key : string) value = key, box value
let RegisterWebApi =
Action<_> (fun (config: HttpConfiguration) ->
// Configure routing
config.MapHttpAttributeRoutes()
config.Routes.MapHttpRoute(
"DefaultApi", // Route name
"api/{controller}/{id}", // URL with parameters
createDefaults [ "controller" => "{controller}";
"id" => RouteParameter.Optional]
) |> ignore
// Configure serialization
config.Formatters.XmlFormatter.UseXmlSerializer <- true
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver
<- Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
// Additional Web API settings
)
let RegisterRoutes(routes:RouteCollection) =
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
createDefaults [ "controller" => "Home" ;
"action" => "Index";
"id" => UrlParameter.Optional; ]
) |> ignore
</code>
<code>[<RequireQualifiedAccess>]
module RouteConfig =
let private createDefaults (propValuePairs : seq<string * obj>) : obj =
let defaults = ExpandoObject() :> IDictionary<string,obj>
propValuePairs |> Seq.iter (fun (key,value) -> defaults.Add(key,value) )
box defaults
/// create a pair, boxing the second item
let inline private (=>) (key : string) value = key, box value
let RegisterWebApi =
Action<_> (fun (config: HttpConfiguration) ->
// Configure routing
config.MapHttpAttributeRoutes()
config.Routes.MapHttpRoute(
"DefaultApi", // Route name
"api/{controller}/{id}", // URL with parameters
createDefaults [ "controller" => "{controller}";
"id" => RouteParameter.Optional]
) |> ignore
// Configure serialization
config.Formatters.XmlFormatter.UseXmlSerializer <- true
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver
<- Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
// Additional Web API settings
)
let RegisterRoutes(routes:RouteCollection) =
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
createDefaults [ "controller" => "Home" ;
"action" => "Index";
"id" => UrlParameter.Optional; ]
) |> ignore
</code>
[<RequireQualifiedAccess>]
module RouteConfig =
let private createDefaults (propValuePairs : seq<string * obj>) : obj =
let defaults = ExpandoObject() :> IDictionary<string,obj>
propValuePairs |> Seq.iter (fun (key,value) -> defaults.Add(key,value) )
box defaults
/// create a pair, boxing the second item
let inline private (=>) (key : string) value = key, box value
let RegisterWebApi =
Action<_> (fun (config: HttpConfiguration) ->
// Configure routing
config.MapHttpAttributeRoutes()
config.Routes.MapHttpRoute(
"DefaultApi", // Route name
"api/{controller}/{id}", // URL with parameters
createDefaults [ "controller" => "{controller}";
"id" => RouteParameter.Optional]
) |> ignore
// Configure serialization
config.Formatters.XmlFormatter.UseXmlSerializer <- true
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver
<- Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
// Additional Web API settings
)
let RegisterRoutes(routes:RouteCollection) =
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
createDefaults [ "controller" => "Home" ;
"action" => "Index";
"id" => UrlParameter.Optional; ]
) |> ignore
I’m mainly wondering if type providers can do something like this at compile time instead of runtime.
3