Skip to content

Commit

Permalink
Fixes #403
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinmoris committed Apr 12, 2020
1 parent 915af0f commit bb4c3a7
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
27 changes: 26 additions & 1 deletion src/Giraffe/ModelBinding.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module ModelParser =
let rec private parseValue (t : Type) (rawValues : StringValues) (culture : CultureInfo) : Result<obj, string> =
// First load up some more type information,
// whether the type is generic, a list or an option type.

let isGeneric = t.GetTypeInfo().IsGenericType
let isList, isOption, genArgType =
if not isGeneric then false, false, null
Expand All @@ -53,7 +54,31 @@ module ModelParser =
genericTypeDef = typedefof<FSharpList<_>>,
genericTypeDef = typedefof<FSharpOption<_>>,
t.GetGenericArguments().[0]
if isList then
if t.IsArray then
let arrArgType = t.GetElementType()
let arrLen = rawValues.Count
let arr = Array.CreateInstance(arrArgType, arrLen)
if arrLen = 0
then Ok (arr :> obj)
else
let (items, _, error) =
Array.fold(
fun (items : Array, idx : int, error : string option) (rawValue : string) ->
let nIdx = idx + 1
match error with
| Some _ -> arr, nIdx, error
| None ->
match parseValue arrArgType (StringValues rawValue) culture with
| Error err -> arr, nIdx, Some err
| Ok item ->
items.SetValue(item, idx)
items, nIdx, None)
(arr, 0, None)
(rawValues.ToArray())
match error with
| Some err -> Error err
| None -> Ok (items :> obj)
else if isList then
let cases = FSharpType.GetUnionCases t
let emptyList = FSharpValue.MakeUnion(cases.[0], [||])
if rawValues.Count = 0
Expand Down
26 changes: 24 additions & 2 deletions tests/Giraffe.Tests/ModelBindingTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ open Microsoft.AspNetCore.Http.Internal
[<CLIMutable>]
type ModelWithOption =
{
OptionalInt: int option
OptionalString: string option
OptionalInt : int option
OptionalString : string option
}

[<CLIMutable>]
Expand Down Expand Up @@ -72,6 +72,11 @@ type Model =
Children : Child[]
}

[<CLIMutable>]
type Model2 = {
SearchTerms : string[]
}

[<CLIMutable>]
type QueryModel =
{
Expand Down Expand Up @@ -103,6 +108,23 @@ type QueryModel =
// ModelParser.tryParse Tests
// ---------------------------------

[<Fact>]
let ``ModelParser.tryParse with model which has primitive array`` () =
let modelData =
dict [
"SearchTerms" , StringValues [| "a"; "abc"; "abcdef" |]
]
let expected =
{
SearchTerms = [| "a"; "abc"; "abcdef" |]
}
let culture = None

let result = ModelParser.tryParse<Model2> culture modelData
match result with
| Ok model -> Assert.Equal(expected, model)
| Error err -> assertFailf "Model didn't bind successfully: %s." err

[<Fact>]
let ``ModelParser.tryParse with complete model data`` () =
let id = Guid.NewGuid()
Expand Down

0 comments on commit bb4c3a7

Please sign in to comment.