5 people like it.
Like the snippet!
Type-safe URL templates for Nancy
The Nancy web framework parses URLs for you, and passes requests under a given URL route and HTTP method to your program. It relies heavily on C# dynamic objects; these don't translate well in F# code, and it's easy to make mistakes that only show up at run time.
Here we define one F# record type for each route, with an attribute that defines the URL, with placeholders for each field in the record. These types implement one generic interface for each HTTP method they support: for GET, PUT and POST, these generic interfaces also specify the types of the HTTP request and response bodies.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
|
#nowarn "40"
#nowarn "42"
namespace Tim.Nancy.Generic
open System
open System.Collections.Generic
open System.IO
open System.Text
open System.Web
open Microsoft.FSharp.Reflection
open Nancy
open Nancy.ModelBinding
open Tavis.UriTemplates
type IRestResource =
interface end
type IRestGet<'Response> =
inherit IRestResource
type IRestPut<'Request, 'Response> =
inherit IRestResource
type IRestPost<'Request, 'Response> =
inherit IRestResource
type IRestDelete =
inherit IRestResource
[<MeasureAnnotatedAbbreviation>]
type string<'Measure> = string
[<AttributeUsage(AttributeTargets.Class, AllowMultiple = true)>]
type UrlAttribute(template : string) =
inherit Attribute()
member t.Template = template
[<AutoOpen>]
module NancyModuleExtensions =
let private memoize (fn : 'a -> 'b) : 'a -> 'b =
let cache = Dictionary()
let syncRoot = obj()
fun a ->
lock syncRoot <| fun () ->
match cache.TryGetValue(a) with
| true, b -> b
| false, _ ->
let b = fn a
cache.[a] <- b
b
let rec private convert : Type -> string -> obj =
memoize <| fun toType ->
if toType.IsGenericType && toType.GetGenericTypeDefinition() = typedefof<option<_>> then
let someCase, convertInner =
FSharpType.GetUnionCases(toType)
|> Array.pick (fun c ->
match c.GetFields() with
| [| f |] -> Some (c, convert f.PropertyType)
| _ -> None)
let ctor = FSharpValue.PreComputeUnionConstructor(someCase)
function
| null | "" -> null
| s -> ctor [| convertInner s |]
elif typeof<IConvertible>.IsAssignableFrom(toType) then
fun s -> Convert.ChangeType(s, toType)
else
failwithf "Can't convert string to %O" toType
[<Sealed>]
type private RestResourceImpl<'Resource> private () =
static let typ = typeof<'Resource>
static let fields, ctor, reader =
if FSharpType.IsUnion(typ) then
match FSharpType.GetUnionCases(typ) with
| [| c |] when c.GetFields() = [| |] ->
let value = FSharpValue.MakeUnion(c, [| |])
[| |], (fun _ -> value), (fun _ -> [| |])
| a -> failwithf "Unions must only have one case. %O has %d cases." typ a.Length
elif FSharpType.IsRecord(typ) then
[| for pi in FSharpType.GetRecordFields(typ) -> pi.Name, convert pi.PropertyType |],
FSharpValue.PreComputeRecordConstructor(typ),
FSharpValue.PreComputeRecordReader(typ)
else
failwithf "Only single-case unions and records are supported, not %O" typ
static let urls =
match typ.GetCustomAttributes(typeof<UrlAttribute>, true) with
| [| |] -> failwithf "No [<Url>] attribute on %O" typeof<'Resource>
| a -> [| for attr in a -> (unbox<UrlAttribute> attr).Template |]
static member Urls = urls
static member PartsToResource (part : string -> string) : 'Resource =
let values = Array.map (fun (name, convert) -> convert (part name)) fields
unbox (ctor values)
static member ResourceToString (resource : 'Resource) : string =
let values = reader resource
let template = UriTemplate(urls.[0])
for name in template.GetParameterNames() do
let value =
match Array.tryFindIndex (fst >> (=) name) fields with
| Some n -> values.[n]
| None -> failwithf "No field called '%s' in %O" name typeof<'Resource>
template.SetParameter(name, value)
template.Resolve()
let private addRoute<'Resource, 'Response when 'Resource :> IRestResource> (t : NancyModule) (builder : NancyModule.RouteBuilder) (fn : 'Resource -> 'Response) (url : string) =
let path, queryParams =
let template = UriTemplate(url)
for name in template.GetParameterNames() do
template.SetParameter(name, "{" + name + "}")
match template.Resolve().Replace("%7B", "{").Replace("%7D", "}").Split([| '?' |], 2) with
| [| |] -> "", Set.empty
| [| path |] -> path, Set.empty
| a -> a.[0], Set.ofSeq (HttpUtility.ParseQueryString(a.[1])).AllKeys
builder.[path] <- fun dict ->
let dict : DynamicDictionary = unbox dict
let query : DynamicDictionary = unbox t.Request.Query
let resource =
RestResourceImpl<_>.PartsToResource <| fun name ->
let dict =
if Set.contains name queryParams then
query
else
dict
unbox (dict.[name] :?> DynamicDictionaryValue).Value
box (fn resource)
[<NoDynamicInvocation>]
let inline private retype (x : 'a) : 'b = (# "" x : 'b #)
type NancyModule with
member t.UrlFor (resource : 'Resource) : string<'Resource> =
retype (t.ModulePath + RestResourceImpl<_>.ResourceToString(resource))
member t.GetT<'Resource, 'Response when 'Resource :> IRestGet<'Response>> (fn : 'Resource -> 'Response) =
Array.iter (addRoute t t.Get fn) RestResourceImpl<'Resource>.Urls
member t.PutT<'Resource, 'Request, 'Response when 'Resource :> IRestPut<'Request, 'Response>> (fn : 'Resource -> 'Request -> 'Response) =
Array.iter (addRoute t t.Put (fun resource -> fn resource (t.Bind<_>()))) RestResourceImpl<'Resource>.Urls
member t.PostT<'Resource, 'Request, 'Response when 'Resource :> IRestPost<'Request, 'Response>> (fn : 'Resource -> 'Request -> 'Response) =
Array.iter (addRoute t t.Post (fun resource -> fn resource (t.Bind<_>()))) RestResourceImpl<'Resource>.Urls
member t.DeleteT<'Resource when 'Resource :> IRestDelete> (fn : 'Resource -> unit) =
Array.iter (addRoute t t.Delete fn) RestResourceImpl<'Resource>.Urls
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
|
open System
open System.Text
open Nancy
open Nancy.Hosting.Self
open Nancy.ModelBinding
[<Url("/hello/{Who}")>]
type Hello = { Who : string }
with interface IRestGet<string>
interface IRestPut<string, unit>
interface IRestDelete
[<Url("/hello{?count}")>]
type Hellos = { Count : int option }
with interface IRestGet<string<Hello> array>
type DemoModule() as t =
inherit NancyModule()
static let mutable greetings = Map.empty
do
t.GetT <| fun (hellos : Hellos) ->
let gs = Option.fold (fun gs count -> Seq.truncate count gs) (Map.toSeq greetings) hellos.Count
[| for who, _ in gs -> t.UrlFor { Who = who } |]
t.GetT <| fun (hello : Hello) ->
let greeting = defaultArg (Map.tryFind hello.Who greetings) "Hello"
sprintf "%s, %s!" greeting hello.Who
t.PutT <| fun (hello : Hello) (greeting : string) ->
greetings <- Map.add hello.Who greeting greetings
t.DeleteT <| fun (hello : Hello) ->
greetings <- Map.remove hello.Who greetings
type StringModelBinder() =
interface IModelBinder with
member t.CanBind typ =
typ = typeof<string>
member t.Bind(context, modelType, instance, config, blacklist) =
let bytes = Array.zeroCreate (int context.Request.Headers.ContentLength)
let length = context.Request.Body.Read(bytes, 0, bytes.Length)
box (Encoding.UTF8.GetString(bytes, 0, length))
module Program =
[<EntryPoint>]
let main _ =
let nancyHost = NancyHost(Uri("http://localhost:8888/nancy/"))
nancyHost.Start()
printfn "Nancy now listening at http://localhost:8888/nancy/. Press Enter to stop."
ignore (Console.ReadLine())
nancyHost.Stop()
0
|
namespace Nancy
namespace System
namespace System.Collections
namespace System.Collections.Generic
namespace System.IO
namespace System.Text
namespace System.Web
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Reflection
namespace Nancy.ModelBinding
namespace Tavis
namespace Tavis.UriTemplates
type IRestResource
Full name: Tim.Nancy.Generic.IRestResource
type IRestGet<'Response> =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestGet<_>
Multiple items
type Response =
new : unit -> Response
member AddCookie : nancyCookie:INancyCookie -> Response + 3 overloads
member ContentType : string with get, set
member Contents : Action<Stream> with get, set
member Cookies : IList<INancyCookie> with get, set
member Dispose : unit -> unit
member Headers : IDictionary<string, string> with get, set
member PreExecute : context:NancyContext -> Task
member ReasonPhrase : string with get, set
member StatusCode : HttpStatusCode with get, set
...
Full name: Nancy.Response
--------------------
Response() : unit
type IRestPut<'Request,'Response> =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestPut<_,_>
Multiple items
type Request =
new : method:string * path:string * scheme:string -> Request + 1 overload
member Body : RequestStream with get, set
member ClientCertificate : X509Certificate with get, set
member Cookies : IDictionary<string, string>
member Dispose : unit -> unit
member Files : IEnumerable<HttpFile>
member Form : obj
member Headers : RequestHeaders with get, set
member Method : string with get, set
member Path : string
...
Full name: Nancy.Request
--------------------
Request(method: string, path: string, scheme: string) : unit
Request(method: string, url: Url, ?body: IO.RequestStream, ?headers: IDictionary<string,IEnumerable<string>>, ?ip: string, ?certificate: byte [], ?protocolVersion: string) : unit
type IRestPost<'Request,'Response> =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestPost<_,_>
type IRestDelete =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestDelete
Multiple items
type MeasureAnnotatedAbbreviationAttribute =
inherit Attribute
new : unit -> MeasureAnnotatedAbbreviationAttribute
Full name: Microsoft.FSharp.Core.MeasureAnnotatedAbbreviationAttribute
--------------------
new : unit -> MeasureAnnotatedAbbreviationAttribute
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
--------------------
type string<'Measure> = string
Full name: Tim.Nancy.Generic.string<_>
Multiple items
type MeasureAttribute =
inherit Attribute
new : unit -> MeasureAttribute
Full name: Microsoft.FSharp.Core.MeasureAttribute
--------------------
new : unit -> MeasureAttribute
Multiple items
type AttributeUsageAttribute =
inherit Attribute
new : validOn:AttributeTargets -> AttributeUsageAttribute
member AllowMultiple : bool with get, set
member Inherited : bool with get, set
member ValidOn : AttributeTargets
Full name: System.AttributeUsageAttribute
--------------------
AttributeUsageAttribute(validOn: AttributeTargets) : unit
type AttributeTargets =
| Assembly = 1
| Module = 2
| Class = 4
| Struct = 8
| Enum = 16
| Constructor = 32
| Method = 64
| Property = 128
| Field = 256
| Event = 512
...
Full name: System.AttributeTargets
field AttributeTargets.Class = 4
Multiple items
type UrlAttribute =
inherit Attribute
new : template:string -> UrlAttribute
member Template : string
Full name: Tim.Nancy.Generic.UrlAttribute
--------------------
new : template:string -> UrlAttribute
val template : string
Multiple items
type Attribute =
member Equals : obj:obj -> bool
member GetHashCode : unit -> int
member IsDefaultAttribute : unit -> bool
member Match : obj:obj -> bool
member TypeId : obj
static member GetCustomAttribute : element:MemberInfo * attributeType:Type -> Attribute + 7 overloads
static member GetCustomAttributes : element:MemberInfo -> Attribute[] + 15 overloads
static member IsDefined : element:MemberInfo * attributeType:Type -> bool + 7 overloads
Full name: System.Attribute
--------------------
Attribute() : unit
val t : UrlAttribute
member UrlAttribute.Template : string
Full name: Tim.Nancy.Generic.UrlAttribute.Template
Multiple items
type AutoOpenAttribute =
inherit Attribute
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
member Path : string
Full name: Microsoft.FSharp.Core.AutoOpenAttribute
--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
val private memoize : fn:('a -> 'b) -> ('a -> 'b) (requires equality)
Full name: Tim.Nancy.Generic.NancyModuleExtensions.memoize
val fn : ('a -> 'b) (requires equality)
val cache : Dictionary<'a,'b> (requires equality)
Multiple items
type Dictionary<'TKey,'TValue> =
new : unit -> Dictionary<'TKey, 'TValue> + 5 overloads
member Add : key:'TKey * value:'TValue -> unit
member Clear : unit -> unit
member Comparer : IEqualityComparer<'TKey>
member ContainsKey : key:'TKey -> bool
member ContainsValue : value:'TValue -> bool
member Count : int
member GetEnumerator : unit -> Enumerator<'TKey, 'TValue>
member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
member Item : 'TKey -> 'TValue with get, set
...
nested type Enumerator
nested type KeyCollection
nested type ValueCollection
Full name: System.Collections.Generic.Dictionary<_,_>
--------------------
Dictionary() : unit
Dictionary(capacity: int) : unit
Dictionary(comparer: IEqualityComparer<'TKey>) : unit
Dictionary(dictionary: IDictionary<'TKey,'TValue>) : unit
Dictionary(capacity: int, comparer: IEqualityComparer<'TKey>) : unit
Dictionary(dictionary: IDictionary<'TKey,'TValue>, comparer: IEqualityComparer<'TKey>) : unit
val syncRoot : Object
type obj = Object
Full name: Microsoft.FSharp.Core.obj
val a : 'a (requires equality)
val lock : lockObject:'Lock -> action:(unit -> 'T) -> 'T (requires reference type)
Full name: Microsoft.FSharp.Core.Operators.lock
Dictionary.TryGetValue(key: 'a, value: byref<'b>) : bool
val b : 'b
val private convert : (Type -> string -> obj)
Full name: Tim.Nancy.Generic.NancyModuleExtensions.convert
type Type =
inherit MemberInfo
member Assembly : Assembly
member AssemblyQualifiedName : string
member Attributes : TypeAttributes
member BaseType : Type
member ContainsGenericParameters : bool
member DeclaringMethod : MethodBase
member DeclaringType : Type
member Equals : o:obj -> bool + 1 overload
member FindInterfaces : filter:TypeFilter * filterCriteria:obj -> Type[]
member FindMembers : memberType:MemberTypes * bindingAttr:BindingFlags * filter:MemberFilter * filterCriteria:obj -> MemberInfo[]
...
Full name: System.Type
val toType : Type
property Type.IsGenericType: bool
Type.GetGenericTypeDefinition() : Type
val typedefof<'T> : Type
Full name: Microsoft.FSharp.Core.Operators.typedefof
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
val someCase : UnionCaseInfo
val convertInner : (string -> obj)
type FSharpType =
static member GetExceptionFields : exceptionType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
static member GetFunctionElements : functionType:Type -> Type * Type
static member GetRecordFields : recordType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
static member GetTupleElements : tupleType:Type -> Type []
static member GetUnionCases : unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo []
static member IsExceptionRepresentation : exceptionType:Type * ?bindingFlags:BindingFlags -> bool
static member IsFunction : typ:Type -> bool
static member IsModule : typ:Type -> bool
static member IsRecord : typ:Type * ?bindingFlags:BindingFlags -> bool
static member IsTuple : typ:Type -> bool
...
Full name: Microsoft.FSharp.Reflection.FSharpType
static member FSharpType.GetUnionCases : unionType:Type * ?allowAccessToPrivateRepresentation:bool -> UnionCaseInfo []
static member FSharpType.GetUnionCases : unionType:Type * ?bindingFlags:Reflection.BindingFlags -> UnionCaseInfo []
type Array =
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...
Full name: System.Array
val pick : chooser:('T -> 'U option) -> array:'T [] -> 'U
Full name: Microsoft.FSharp.Collections.Array.pick
val c : UnionCaseInfo
member UnionCaseInfo.GetFields : unit -> Reflection.PropertyInfo []
val f : Reflection.PropertyInfo
union case Option.Some: Value: 'T -> Option<'T>
property Reflection.PropertyInfo.PropertyType: Type
union case Option.None: Option<'T>
val ctor : (obj [] -> obj)
type FSharpValue =
static member GetExceptionFields : exn:obj * ?bindingFlags:BindingFlags -> obj []
static member GetRecordField : record:obj * info:PropertyInfo -> obj
static member GetRecordFields : record:obj * ?bindingFlags:BindingFlags -> obj []
static member GetTupleField : tuple:obj * index:int -> obj
static member GetTupleFields : tuple:obj -> obj []
static member GetUnionFields : value:obj * unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo * obj []
static member MakeFunction : functionType:Type * implementation:(obj -> obj) -> obj
static member MakeRecord : recordType:Type * values:obj [] * ?bindingFlags:BindingFlags -> obj
static member MakeTuple : tupleElements:obj [] * tupleType:Type -> obj
static member MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:BindingFlags -> obj
...
Full name: Microsoft.FSharp.Reflection.FSharpValue
static member FSharpValue.PreComputeUnionConstructor : unionCase:UnionCaseInfo * ?allowAccessToPrivateRepresentation:bool -> (obj [] -> obj)
static member FSharpValue.PreComputeUnionConstructor : unionCase:UnionCaseInfo * ?bindingFlags:Reflection.BindingFlags -> (obj [] -> obj)
val s : string
val typeof<'T> : Type
Full name: Microsoft.FSharp.Core.Operators.typeof
type IConvertible =
member GetTypeCode : unit -> TypeCode
member ToBoolean : provider:IFormatProvider -> bool
member ToByte : provider:IFormatProvider -> byte
member ToChar : provider:IFormatProvider -> char
member ToDateTime : provider:IFormatProvider -> DateTime
member ToDecimal : provider:IFormatProvider -> decimal
member ToDouble : provider:IFormatProvider -> float
member ToInt16 : provider:IFormatProvider -> int16
member ToInt32 : provider:IFormatProvider -> int
member ToInt64 : provider:IFormatProvider -> int64
...
Full name: System.IConvertible
type Convert =
static val DBNull : obj
static member ChangeType : value:obj * typeCode:TypeCode -> obj + 3 overloads
static member FromBase64CharArray : inArray:char[] * offset:int * length:int -> byte[]
static member FromBase64String : s:string -> byte[]
static member GetTypeCode : value:obj -> TypeCode
static member IsDBNull : value:obj -> bool
static member ToBase64CharArray : inArray:byte[] * offsetIn:int * length:int * outArray:char[] * offsetOut:int -> int + 1 overload
static member ToBase64String : inArray:byte[] -> string + 3 overloads
static member ToBoolean : value:obj -> bool + 17 overloads
static member ToByte : value:obj -> byte + 18 overloads
...
Full name: System.Convert
Convert.ChangeType(value: obj, conversionType: Type) : obj
Convert.ChangeType(value: obj, typeCode: TypeCode) : obj
Convert.ChangeType(value: obj, conversionType: Type, provider: IFormatProvider) : obj
Convert.ChangeType(value: obj, typeCode: TypeCode, provider: IFormatProvider) : obj
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
Multiple items
type SealedAttribute =
inherit Attribute
new : unit -> SealedAttribute
new : value:bool -> SealedAttribute
member Value : bool
Full name: Microsoft.FSharp.Core.SealedAttribute
--------------------
new : unit -> SealedAttribute
new : value:bool -> SealedAttribute
Multiple items
type private RestResourceImpl<'Resource> =
new : unit -> RestResourceImpl<'Resource>
static member PartsToResource : part:(string -> string) -> 'Resource
static member ResourceToString : resource:'Resource -> string
static member Urls : string []
Full name: Tim.Nancy.Generic.NancyModuleExtensions.RestResourceImpl<_>
--------------------
private new : unit -> RestResourceImpl<'Resource>
val typ : Type
val fields : (string * (string -> obj)) []
val reader : (obj -> obj [])
static member FSharpType.IsUnion : typ:Type * ?allowAccessToPrivateRepresentation:bool -> bool
static member FSharpType.IsUnion : typ:Type * ?bindingFlags:Reflection.BindingFlags -> bool
val value : obj
static member FSharpValue.MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?allowAccessToPrivateRepresentation:bool -> obj
static member FSharpValue.MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:Reflection.BindingFlags -> obj
val a : UnionCaseInfo []
property Array.Length: int
static member FSharpType.IsRecord : typ:Type * ?allowAccessToPrivateRepresentation:bool -> bool
static member FSharpType.IsRecord : typ:Type * ?bindingFlags:Reflection.BindingFlags -> bool
val pi : Reflection.PropertyInfo
static member FSharpType.GetRecordFields : recordType:Type * ?allowAccessToPrivateRepresentation:bool -> Reflection.PropertyInfo []
static member FSharpType.GetRecordFields : recordType:Type * ?bindingFlags:Reflection.BindingFlags -> Reflection.PropertyInfo []
property Reflection.MemberInfo.Name: string
static member FSharpValue.PreComputeRecordConstructor : recordType:Type * ?allowAccessToPrivateRepresentation:bool -> (obj [] -> obj)
static member FSharpValue.PreComputeRecordConstructor : recordType:Type * ?bindingFlags:Reflection.BindingFlags -> (obj [] -> obj)
static member FSharpValue.PreComputeRecordReader : recordType:Type * ?allowAccessToPrivateRepresentation:bool -> (obj -> obj [])
static member FSharpValue.PreComputeRecordReader : recordType:Type * ?bindingFlags:Reflection.BindingFlags -> (obj -> obj [])
val urls : string []
Reflection.MemberInfo.GetCustomAttributes(inherit: bool) : obj []
Reflection.MemberInfo.GetCustomAttributes(attributeType: Type, inherit: bool) : obj []
val a : obj []
val attr : obj
val unbox : value:obj -> 'T
Full name: Microsoft.FSharp.Core.Operators.unbox
static member private RestResourceImpl.Urls : string []
Full name: Tim.Nancy.Generic.NancyModuleExtensions.RestResourceImpl`1.Urls
static member private RestResourceImpl.PartsToResource : part:(string -> string) -> 'Resource
Full name: Tim.Nancy.Generic.NancyModuleExtensions.RestResourceImpl`1.PartsToResource
val part : (string -> string)
val values : obj []
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []
Full name: Microsoft.FSharp.Collections.Array.map
val name : string
val convert : (string -> obj)
static member private RestResourceImpl.ResourceToString : resource:'Resource -> string
Full name: Tim.Nancy.Generic.NancyModuleExtensions.RestResourceImpl`1.ResourceToString
val resource : 'Resource
val template : UriTemplate
Multiple items
type UriTemplate =
new : template:string * ?resolvePartially:bool * ?caseInsensitiveParameterNames:bool -> UriTemplate
member ClearParameter : name:string -> unit
member GetParameterNames : unit -> IEnumerable<string>
member Resolve : unit -> string
member SetParameter : name:string * value:obj -> unit + 3 overloads
member ToString : unit -> string
Full name: Tavis.UriTemplates.UriTemplate
--------------------
UriTemplate(template: string, ?resolvePartially: bool, ?caseInsensitiveParameterNames: bool) : unit
UriTemplate.GetParameterNames() : IEnumerable<string>
val tryFindIndex : predicate:('T -> bool) -> array:'T [] -> int option
Full name: Microsoft.FSharp.Collections.Array.tryFindIndex
val fst : tuple:('T1 * 'T2) -> 'T1
Full name: Microsoft.FSharp.Core.Operators.fst
val n : int
UriTemplate.SetParameter(name: string, value: IDictionary<string,string>) : unit
UriTemplate.SetParameter(name: string, value: IEnumerable<string>) : unit
UriTemplate.SetParameter(name: string, value: string) : unit
UriTemplate.SetParameter(name: string, value: obj) : unit
UriTemplate.Resolve() : string
val private addRoute : t:NancyModule -> builder:NancyModule.RouteBuilder -> fn:(#IRestResource -> 'Response) -> url:string -> unit
Full name: Tim.Nancy.Generic.NancyModuleExtensions.addRoute
val t : NancyModule
type NancyModule =
member After : AfterPipeline with get, set
member Before : BeforePipeline with get, set
member Context : NancyContext with get, set
member Delete : RouteBuilder
member Get : RouteBuilder
member Head : RouteBuilder
member ModelBinderLocator : IModelBinderLocator with get, set
member ModelValidationResult : ModelValidationResult with get, set
member ModulePath : string with get, set
member Negotiate : Negotiator
...
nested type RouteBuilder
Full name: Nancy.NancyModule
val builder : NancyModule.RouteBuilder
type RouteBuilder =
new : method:string * parentModule:NancyModule -> RouteBuilder
member Item : string -> Func<obj, obj> with set
member Item : string * Func<NancyContext, bool> -> Func<obj, obj> with set
member Item : string * bool -> Func<obj, CancellationToken, Task<obj>> with set
member Item : string * string -> Func<obj, obj> with set
member Item : string * Func<NancyContext, bool> * bool -> Func<obj, CancellationToken, Task<obj>> with set
member Item : string * string * Func<NancyContext, bool> -> Func<obj, obj> with set
member Item : string * string * bool -> Func<obj, CancellationToken, Task<obj>> with set
member Item : string * string * Func<NancyContext, bool> * bool -> Func<obj, CancellationToken, Task<obj>> with set
Full name: Nancy.NancyModule.RouteBuilder
val fn : (#IRestResource -> 'Response)
val url : string
val path : string
val queryParams : Set<string>
Multiple items
module Set
from Microsoft.FSharp.Collections
--------------------
type Set<'T (requires comparison)> =
interface IComparable
interface IEnumerable
interface IEnumerable<'T>
interface ICollection<'T>
new : elements:seq<'T> -> Set<'T>
member Add : value:'T -> Set<'T>
member Contains : value:'T -> bool
override Equals : obj -> bool
member IsProperSubsetOf : otherSet:Set<'T> -> bool
member IsProperSupersetOf : otherSet:Set<'T> -> bool
...
Full name: Microsoft.FSharp.Collections.Set<_>
--------------------
new : elements:seq<'T> -> Set<'T>
val empty<'T (requires comparison)> : Set<'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Set.empty
val a : string []
val ofSeq : elements:seq<'T> -> Set<'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Set.ofSeq
Multiple items
type HttpUtility =
new : unit -> HttpUtility
static member HtmlAttributeEncode : s:string -> string + 1 overload
static member HtmlDecode : s:string -> string + 1 overload
static member HtmlEncode : s:string -> string + 2 overloads
static member JavaScriptStringEncode : value:string -> string + 1 overload
static member ParseQueryString : query:string -> NameValueCollection + 1 overload
static member UrlDecode : str:string -> string + 3 overloads
static member UrlDecodeToBytes : str:string -> byte[] + 3 overloads
static member UrlEncode : str:string -> string + 3 overloads
static member UrlEncodeToBytes : str:string -> byte[] + 3 overloads
...
Full name: System.Web.HttpUtility
--------------------
HttpUtility() : unit
HttpUtility.ParseQueryString(query: string) : Collections.Specialized.NameValueCollection
HttpUtility.ParseQueryString(query: string, encoding: Encoding) : Collections.Specialized.NameValueCollection
val dict : obj
val dict : DynamicDictionary
Multiple items
type DynamicDictionary =
inherit DynamicObject
new : unit -> DynamicDictionary
member Add : item:KeyValuePair<string, obj> -> unit + 1 overload
member Clear : unit -> unit
member Contains : item:KeyValuePair<string, obj> -> bool
member ContainsKey : key:string -> bool
member CopyTo : array:KeyValuePair<string, obj>[] * arrayIndex:int -> unit
member Count : int
member Equals : other:DynamicDictionary -> bool + 1 overload
member GetDynamicMemberNames : unit -> IEnumerable<string>
member GetEnumerator : unit -> IEnumerator<string>
...
Full name: Nancy.DynamicDictionary
--------------------
DynamicDictionary() : unit
val query : DynamicDictionary
property NancyModule.Request: Request
property Request.Query: obj
val resource : #IRestResource
type private RestResourceImpl<'Resource> =
new : unit -> RestResourceImpl<'Resource>
static member PartsToResource : part:(string -> string) -> 'Resource
static member ResourceToString : resource:'Resource -> string
static member Urls : string []
Full name: Tim.Nancy.Generic.NancyModuleExtensions.RestResourceImpl<_>
val contains : element:'T -> set:Set<'T> -> bool (requires comparison)
Full name: Microsoft.FSharp.Collections.Set.contains
Multiple items
type DynamicDictionaryValue =
inherit DynamicObject
new : value:obj -> DynamicDictionaryValue
member Default<'T> : ?defaultValue:'T -> 'T
member Equals : compareValue:DynamicDictionaryValue -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member HasValue : bool
member ToBoolean : provider:IFormatProvider -> bool
member ToByte : provider:IFormatProvider -> byte
member ToChar : provider:IFormatProvider -> char
member ToDateTime : provider:IFormatProvider -> DateTime
...
Full name: Nancy.DynamicDictionaryValue
--------------------
DynamicDictionaryValue(value: obj) : unit
val box : value:'T -> obj
Full name: Microsoft.FSharp.Core.Operators.box
Multiple items
type NoDynamicInvocationAttribute =
inherit Attribute
new : unit -> NoDynamicInvocationAttribute
Full name: Microsoft.FSharp.Core.NoDynamicInvocationAttribute
--------------------
new : unit -> NoDynamicInvocationAttribute
val private retype : x:'a -> 'b
Full name: Tim.Nancy.Generic.NancyModuleExtensions.retype
val x : 'a
member NancyModule.UrlFor : resource:'Resource -> string<'Resource>
Full name: Tim.Nancy.Generic.NancyModuleExtensions.UrlFor
property NancyModule.ModulePath: string
member NancyModule.GetT : fn:(#IRestGet<'Response> -> 'Response) -> unit
Full name: Tim.Nancy.Generic.NancyModuleExtensions.GetT
val fn : (#IRestGet<'Response> -> 'Response)
val iter : action:('T -> unit) -> array:'T [] -> unit
Full name: Microsoft.FSharp.Collections.Array.iter
property NancyModule.Get: NancyModule.RouteBuilder
member NancyModule.PutT : fn:(#IRestPut<'Request,'Response> -> 'Request -> 'Response) -> unit
Full name: Tim.Nancy.Generic.NancyModuleExtensions.PutT
val fn : (#IRestPut<'Request,'Response> -> 'Request -> 'Response)
property NancyModule.Put: NancyModule.RouteBuilder
val resource : #IRestPut<'Request,'Response>
(extension) INancyModule.Bind<'TModel>() : 'TModel
(extension) INancyModule.Bind([<ParamArray>] blacklistedProperties: string []) : obj
(extension) INancyModule.Bind<'TModel>([<ParamArray>] blacklistedProperties: string []) : 'TModel
(extension) INancyModule.Bind<'TModel>([<ParamArray>] blacklistedProperties: Linq.Expressions.Expression<Func<'TModel,obj>> []) : 'TModel
(extension) INancyModule.Bind<'TModel>(configuration: BindingConfig) : 'TModel
(extension) INancyModule.Bind(configuration: BindingConfig, [<ParamArray>] blacklistedProperties: string []) : obj
(extension) INancyModule.Bind<'TModel>(configuration: BindingConfig, [<ParamArray>] blacklistedProperties: string []) : 'TModel
(extension) INancyModule.Bind<'TModel>(configuration: BindingConfig, blacklistedProperty: Linq.Expressions.Expression<Func<'TModel,obj>>) : 'TModel
(extension) INancyModule.Bind<'TModel>(configuration: BindingConfig, [<ParamArray>] blacklistedProperties: Linq.Expressions.Expression<Func<'TModel,obj>> []) : 'TModel
member NancyModule.PostT : fn:(#IRestPost<'Request,'Response> -> 'Request -> 'Response) -> unit
Full name: Tim.Nancy.Generic.NancyModuleExtensions.PostT
val fn : (#IRestPost<'Request,'Response> -> 'Request -> 'Response)
property NancyModule.Post: NancyModule.RouteBuilder
val resource : #IRestPost<'Request,'Response>
member NancyModule.DeleteT : fn:(#IRestDelete -> unit) -> unit
Full name: Tim.Nancy.Generic.NancyModuleExtensions.DeleteT
val fn : (#IRestDelete -> unit)
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
property NancyModule.Delete: NancyModule.RouteBuilder
namespace Nancy.Hosting
namespace Nancy.Hosting.Self
Multiple items
type Url =
new : unit -> Url + 1 overload
member BasePath : string with get, set
member Clone : unit -> Url
member HostName : string with get, set
member IsSecure : bool
member Path : string with get, set
member Port : Nullable<int> with get, set
member Query : string with get, set
member Scheme : string with get, set
member SiteBase : string
...
Full name: Nancy.Url
--------------------
type UrlAttribute =
inherit Attribute
new : template:string -> UrlAttribute
member Template : string
Full name: Tim.Nancy.Generic.UrlAttribute
--------------------
Url() : unit
Url(url: string) : unit
--------------------
new : template:string -> UrlAttribute
type Hello =
{Who: string;}
interface IRestDelete
interface IRestPut<string,unit>
interface IRestGet<string>
Full name: Tim.Nancy.Generic.Hello
Hello.Who: string
type Hellos =
{Count: int option;}
interface IRestGet<string<Hello> array>
Full name: Tim.Nancy.Generic.Hellos
Hellos.Count: int option
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
type 'T array = 'T []
Full name: Microsoft.FSharp.Core.array<_>
Multiple items
type DemoModule =
inherit NancyModule
new : unit -> DemoModule
Full name: Tim.Nancy.Generic.DemoModule
--------------------
new : unit -> DemoModule
val t : DemoModule
Multiple items
type NancyModule =
member After : AfterPipeline with get, set
member Before : BeforePipeline with get, set
member Context : NancyContext with get, set
member Delete : RouteBuilder
member Get : RouteBuilder
member Head : RouteBuilder
member ModelBinderLocator : IModelBinderLocator with get, set
member ModelValidationResult : ModelValidationResult with get, set
member ModulePath : string with get, set
member Negotiate : Negotiator
...
nested type RouteBuilder
Full name: Nancy.NancyModule
--------------------
NancyModule() : unit
NancyModule(modulePath: string) : unit
val mutable greetings : Map<string,string>
Multiple items
module Map
from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
override Equals : obj -> bool
member Remove : key:'Key -> Map<'Key,'Value>
...
Full name: Microsoft.FSharp.Collections.Map<_,_>
--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.empty
val hellos : Hellos
val gs : seq<string * string>
module Option
from Microsoft.FSharp.Core
val fold : folder:('State -> 'T -> 'State) -> state:'State -> option:'T option -> 'State
Full name: Microsoft.FSharp.Core.Option.fold
val count : int
module Seq
from Microsoft.FSharp.Collections
val truncate : count:int -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.truncate
val toSeq : table:Map<'Key,'T> -> seq<'Key * 'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.toSeq
val who : string
member NancyModule.UrlFor : resource:'Resource -> string<'Resource>
member NancyModule.GetT : fn:(#IRestGet<'Response> -> 'Response) -> unit
val hello : Hello
val greeting : string
val defaultArg : arg:'T option -> defaultValue:'T -> 'T
Full name: Microsoft.FSharp.Core.Operators.defaultArg
val tryFind : key:'Key -> table:Map<'Key,'T> -> 'T option (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.tryFind
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
member NancyModule.PutT : fn:(#IRestPut<'Request,'Response> -> 'Request -> 'Response) -> unit
val add : key:'Key -> value:'T -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.add
member NancyModule.DeleteT : fn:(#IRestDelete -> unit) -> unit
val remove : key:'Key -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.remove
Multiple items
type StringModelBinder =
interface IModelBinder
new : unit -> StringModelBinder
Full name: Tim.Nancy.Generic.StringModelBinder
--------------------
new : unit -> StringModelBinder
type IModelBinder =
member CanBind : modelType:Type -> bool
Full name: Nancy.ModelBinding.IModelBinder
val t : StringModelBinder
override StringModelBinder.CanBind : typ:Type -> bool
Full name: Tim.Nancy.Generic.StringModelBinder.CanBind
override StringModelBinder.Bind : context:NancyContext * modelType:Type * instance:obj * config:BindingConfig * blacklist:string [] -> obj
Full name: Tim.Nancy.Generic.StringModelBinder.Bind
val context : NancyContext
val modelType : Type
val instance : obj
val config : BindingConfig
val blacklist : string []
val bytes : byte []
val zeroCreate : count:int -> 'T []
Full name: Microsoft.FSharp.Collections.Array.zeroCreate
property NancyContext.Request: Request
property Request.Headers: RequestHeaders
property RequestHeaders.ContentLength: int64
val length : int
property Request.Body: IO.RequestStream
IO.RequestStream.Read(buffer: byte [], offset: int, count: int) : int
type Encoding =
member BodyName : string
member Clone : unit -> obj
member CodePage : int
member DecoderFallback : DecoderFallback with get, set
member EncoderFallback : EncoderFallback with get, set
member EncodingName : string
member Equals : value:obj -> bool
member GetByteCount : chars:char[] -> int + 3 overloads
member GetBytes : chars:char[] -> byte[] + 5 overloads
member GetCharCount : bytes:byte[] -> int + 2 overloads
...
Full name: System.Text.Encoding
property Encoding.UTF8: Encoding
Encoding.GetString(bytes: byte []) : string
Encoding.GetString(bytes: byte [], index: int, count: int) : string
module Program
from Tim.Nancy.Generic
Multiple items
type EntryPointAttribute =
inherit Attribute
new : unit -> EntryPointAttribute
Full name: Microsoft.FSharp.Core.EntryPointAttribute
--------------------
new : unit -> EntryPointAttribute
val main : string [] -> int
Full name: Tim.Nancy.Generic.Program.main
val nancyHost : NancyHost
Multiple items
type NancyHost =
new : [<ParamArray>] baseUris:Uri[] -> NancyHost + 5 overloads
member Dispose : unit -> unit
member Start : unit -> unit
member Stop : unit -> unit
Full name: Nancy.Hosting.Self.NancyHost
--------------------
NancyHost([<ParamArray>] baseUris: Uri []) : unit
NancyHost(configuration: HostConfiguration, [<ParamArray>] baseUris: Uri []) : unit
NancyHost(bootstrapper: Bootstrapper.INancyBootstrapper, [<ParamArray>] baseUris: Uri []) : unit
NancyHost(baseUri: Uri, bootstrapper: Bootstrapper.INancyBootstrapper) : unit
NancyHost(bootstrapper: Bootstrapper.INancyBootstrapper, configuration: HostConfiguration, [<ParamArray>] baseUris: Uri []) : unit
NancyHost(baseUri: Uri, bootstrapper: Bootstrapper.INancyBootstrapper, configuration: HostConfiguration) : unit
Multiple items
type Uri =
new : uriString:string -> Uri + 5 overloads
member AbsolutePath : string
member AbsoluteUri : string
member Authority : string
member DnsSafeHost : string
member Equals : comparand:obj -> bool
member Fragment : string
member GetComponents : components:UriComponents * format:UriFormat -> string
member GetHashCode : unit -> int
member GetLeftPart : part:UriPartial -> string
...
Full name: System.Uri
--------------------
Uri(uriString: string) : unit
Uri(uriString: string, uriKind: UriKind) : unit
Uri(baseUri: Uri, relativeUri: string) : unit
Uri(baseUri: Uri, relativeUri: Uri) : unit
NancyHost.Start() : unit
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
type Console =
static member BackgroundColor : ConsoleColor with get, set
static member Beep : unit -> unit + 1 overload
static member BufferHeight : int with get, set
static member BufferWidth : int with get, set
static member CapsLock : bool
static member Clear : unit -> unit
static member CursorLeft : int with get, set
static member CursorSize : int with get, set
static member CursorTop : int with get, set
static member CursorVisible : bool with get, set
...
Full name: System.Console
Console.ReadLine() : string
NancyHost.Stop() : unit
More information