Update album

We have delete, we have create, so we're left with the update part only. This one will be fairly easy, as it's gonna be very similar to create (we can reuse the album form we declared in Form module).

First add editAlbum in View:

View.fs

 175: 
 176: 
 177: 
 178: 
 179: 
 180: 
 181: 
 182: 
 183: 
 184: 
 185: 
 186: 
 187: 
 188: 
 189: 
 190: 
 191: 
 192: 
 193: 
 194: 
 195: 
 196: 
 197: 
 198: 
 199: 
 200: 
 201: 
 202: 
 203: 
 204: 
 205: 
 206: 
 207: 
 208: 
 209: 
 210: 
let editAlbum (album : Db.Album) genres artists = [ h2 "Edit" renderForm { Form = Form.album Fieldsets = [ { Legend = "Album" Fields = [ { Label = "Genre" Html = selectInput (fun f -> <@ f.GenreId @>) genres (Some (decimal album.Genreid)) } { Label = "Artist" Html = selectInput (fun f -> <@ f.ArtistId @>) artists (Some (decimal album.Artistid)) } { Label = "Title" Html = formInput (fun f -> <@ f.Title @>) ["value", album.Title] } { Label = "Price" Html = formInput (fun f -> <@ f.Price @>) ["value", formatDec album.Price] } { Label = "Album Art Url" Html = formInput (fun f -> <@ f.ArtUrl @>) ["value", "/placeholder.gif"] } ] } ] SubmitText = "Save Changes" } div [] [ a Path.Admin.manage [] [Text "Back to list"] ] ]

Next, add corresponding path:

Path.fs

  16: 
  17: 
  18: 
  19: 
  20: 
module Admin = let manage = "/admin/manage" let createAlbum = "/admin/create" let editAlbum : IntPath = "/admin/edit/%d" let deleteAlbum : IntPath = "/admin/delete/%d"

Link in manage view to edit the album, also with additional link to details and pipe separators (Text):

View.fs

 119: 
 120: 
 121: 
 122: 
 123: 
 124: 
 125: 
 126: 
 127: 
 128: 
yield td [ a (sprintf Path.Admin.editAlbum album.Albumid) [] [Text "Edit"] Text " | " a (sprintf Path.Store.details album.Albumid) [] [Text "Details"] Text " | " a (sprintf Path.Admin.deleteAlbum album.Albumid) [] [Text "Delete"] ] ] ] ]

updateAlbum in Db module:

Db.fs

  69: 
  70: 
  71: 
  72: 
  73: 
  74: 
let updateAlbum (album : Album) (artistId, genreId, price, title) (ctx : DbContext) = album.Artistid <- artistId album.Genreid <- genreId album.Price <- price album.Title <- title ctx.SubmitUpdates()

editAlbum WebPart in App module:

App.fs

  69: 
  70: 
  71: 
  72: 
  73: 
  74: 
  75: 
  76: 
  77: 
  78: 
  79: 
  80: 
  81: 
  82: 
  83: 
  84: 
  85: 
  86: 
  87: 
  88: 
  89: 
  90: 
  91: 
  92: 
let editAlbum id = let ctx = Db.getContext() match Db.getAlbum id ctx with | Some album -> choose [ GET >=> warbler (fun _ -> let genres = Db.getGenres ctx |> List.map (fun g -> decimal g.Genreid, g.Name) let artists = Db.getArtists ctx |> List.map (fun g -> decimal g.Artistid, g.Name) html (View.editAlbum album genres artists)) POST >=> bindToForm Form.album (fun form -> Db.updateAlbum album (int form.ArtistId, int form.GenreId, form.Price, form.Title) ctx Redirection.FOUND Path.Admin.manage) ] | None -> never

and finally pathScan in main choose WebPart:

App.fs

 117: 
pathScan Path.Admin.editAlbum editAlbum

Comments to above snippets:

  • editAlbum View looks very much the same as the createAlbum. The only significant difference is that it has all the filed values pre-filled.
  • in Db.updateAlbum we can see examples of property setters. This is the way SQLProvider mutates our Album value, while keeping track on what has changed before SubmitUpdates()
  • warbler is needed in editAlbum GET handler to prevent eager evaluation
  • but it's not necessary for POST, because POST needs to parse the incoming request, thus the evaluation is postponed upon the successful parsing.
  • after the album is updated, a redirection to manage is applied

Note: SQLProvider allows to change Album properties after the object has been instantiated - that's generally against the immutability concept that's propagated in the functional programming paradigm. We need to remember however, that F# is not pure functional programming language, but rather "functional first". This means that while it encourages to write in functional style, it still allows to use Object Oriented constructs. This often turns out to be useful, for example when we need to improve performance.

Pheeew, this section was long, but also very productive. Looks like we can already do some serious interaction with the application!

Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
namespace FSharp.Data.Sql
Multiple items
type LiteralAttribute =
inherit Attribute
new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
val ConnectionString : string

Full name: SuaveMusicStore.Db.ConnectionString
type Sql = SqlDataProvider<...>

Full name: SuaveMusicStore.Db.Sql
type SqlDataProvider

Full name: FSharp.Data.Sql.SqlDataProvider


<summary>Typed representation of a database</summary>
<param name='ConnectionString'>The connection string for the SQL database</param>
<param name='ConnectionStringName'>The connection string name to select from a configuration file</param>
<param name='DatabaseVendor'> The target database vendor</param>
<param name='IndividualsAmount'>The amount of sample entities to project into the type system for each SQL entity type. Default 1000.</param>
<param name='UseOptionTypes'>If true, F# option types will be used in place of nullable database columns. If false, you will always receive the default value of the column's type even if it is null in the database.</param>
<param name='ResolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types.</param>
<param name='Owner'>The owner of the schema for this provider to resolve (Oracle Only)</param>
<param name='CaseSensitivityChange'>Should we do ToUpper or ToLower when generating table names?</param>
<param name='TableNames'>Comma separated table names list to limit a number of tables in big instances. The names can have '%' sign to handle it as in the 'LIKE' query (Oracle and MSSQL Only)</param>
<param name='OdbcQuote'>Odbc quote characters: Quote characters for the table and column names: `alias`, [alias]</param>
<param name='SQLiteLibrary'>Use System.Data.SQLite or Mono.Data.SQLite or select automatically (SQLite only)</param>
namespace FSharp.Data.Sql.Common
type DatabaseProviderTypes =
| MSSQLSERVER = 0
| SQLITE = 1
| POSTGRESQL = 2
| MYSQL = 3
| ORACLE = 4
| MSACCESS = 5
| ODBC = 6
| FIREBIRD = 7

Full name: FSharp.Data.Sql.Common.DatabaseProviderTypes
Common.DatabaseProviderTypes.POSTGRESQL: Common.DatabaseProviderTypes = 2
type CaseSensitivityChange =
| ORIGINAL = 0
| TOUPPER = 1
| TOLOWER = 2

Full name: FSharp.Data.Sql.Common.CaseSensitivityChange
Common.CaseSensitivityChange.ORIGINAL: Common.CaseSensitivityChange = 0
type DbContext = SqlDataProvider<...>.dataContext

Full name: SuaveMusicStore.Db.DbContext
type dataContext =
member ClearUpdates : unit -> List<SqlEntity>
member CreateConnection : unit -> IDbConnection
member GetUpdates : unit -> List<SqlEntity>
member Public : publicSchema
member SubmitUpdates : unit -> Unit
member SubmitUpdatesAsync : unit -> Async<Unit>
nested type public.albumdetails.Individuals
nested type public.albumdetailsEntity
nested type public.albums.Individuals
nested type public.albumsEntity
...

Full name: FSharp.Data.Sql.SqlDataProvider,DatabaseVendor="2",ConnectionString="Server=192.168.99.100;Database=suavemusicstore;User Id=suave;Password=1234;",CaseSensitivityChange="0".dataContext
type Album = SqlDataProvider<...>.dataContext.public.albumsEntity

Full name: SuaveMusicStore.Db.Album
type Genre = SqlDataProvider<...>.dataContext.public.genresEntity

Full name: SuaveMusicStore.Db.Genre
type AlbumDetails = SqlDataProvider<...>.dataContext.public.albumdetailsEntity

Full name: SuaveMusicStore.Db.AlbumDetails
type Artist = SqlDataProvider<...>.dataContext.public.artistsEntity

Full name: SuaveMusicStore.Db.Artist
val getContext : unit -> SqlDataProvider<...>.dataContext

Full name: SuaveMusicStore.Db.getContext
SqlDataProvider<...>.GetDataContext() : SqlDataProvider<...>.dataContext


<summary>Returns an instance of the SQL Provider using the static parameters</summary>

SqlDataProvider<...>.GetDataContext(transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext


<summary>Returns an instance of the SQL Provider</summary>
<param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>

SqlDataProvider<...>.GetDataContext(connectionString: string) : SqlDataProvider<...>.dataContext


<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>

SqlDataProvider<...>.GetDataContext(connectionString: string, transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext


<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
<param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>

SqlDataProvider<...>.GetDataContext(connectionString: string, resolutionPath: string) : SqlDataProvider<...>.dataContext


<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
<param name='resolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types</param>

SqlDataProvider<...>.GetDataContext(connectionString: string, resolutionPath: string, transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext


<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
<param name='resolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types</param>
<param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>
val getGenres : ctx:DbContext -> Genre list

Full name: SuaveMusicStore.Db.getGenres
val ctx : DbContext
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
property SqlDataProvider<...>.dataContext.Public: SqlDataProvider<...>.dataContext.publicSchema
property SqlDataProvider<...>.dataContext.publicSchema.Genres: SqlDataProvider<...>.dataContext.publicSchema.public.genres


<summary> The base table genres belonging to schema public</summary>
Multiple items
module Seq

from FSharp.Data.Sql

--------------------
module Seq

from Microsoft.FSharp.Collections
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val getAlbumsForGenre : genreName:string -> ctx:DbContext -> Album list

Full name: SuaveMusicStore.Db.getAlbumsForGenre
val genreName : string
val query : Linq.QueryBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
val album : SqlDataProvider<...>.dataContext.public.albumsEntity
property SqlDataProvider<...>.dataContext.publicSchema.Albums: SqlDataProvider<...>.dataContext.publicSchema.public.albums


<summary> The base table albums belonging to schema public</summary>
custom operation: join var in collection on (outerKey = innerKey). Note that parentheses are required after 'on'

Calls Linq.QueryBuilder.Join
val genre : SqlDataProvider<...>.dataContext.public.genresEntity
property SqlDataProvider<...>.dataContext.public.genresEntity.Genreid: int


<summary> integer</summary>
custom operation: where (bool)

Calls Linq.QueryBuilder.Where
property SqlDataProvider<...>.dataContext.public.genresEntity.Name: string


<summary> character varying(120)</summary>
custom operation: select ('Result)

Calls Linq.QueryBuilder.Select
val getAlbumDetails : id:int -> ctx:DbContext -> AlbumDetails option

Full name: SuaveMusicStore.Db.getAlbumDetails
val id : int
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
val album : SqlDataProvider<...>.dataContext.public.albumdetailsEntity
property SqlDataProvider<...>.dataContext.publicSchema.Albumdetails: SqlDataProvider<...>.dataContext.publicSchema.public.albumdetails


<summary> The view albumdetails belonging to schema public</summary>
property SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumid: int


<summary> integer</summary>
val tryHead : source:seq<'T> -> 'T option

Full name: Microsoft.FSharp.Collections.Seq.tryHead
val getAlbumsDetails : ctx:DbContext -> AlbumDetails list

Full name: SuaveMusicStore.Db.getAlbumsDetails
Multiple items
module List

from FSharp.Data.Sql

--------------------
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val sortBy : projection:('T -> 'Key) -> list:'T list -> 'T list (requires comparison)

Full name: Microsoft.FSharp.Collections.List.sortBy
val a : SqlDataProvider<...>.dataContext.public.albumdetailsEntity
property SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Artist: string


<summary> character varying(120)</summary>
val getAlbum : id:int -> ctx:DbContext -> Album option

Full name: SuaveMusicStore.Db.getAlbum
property SqlDataProvider<...>.dataContext.public.albumsEntity.Albumid: int


<summary> integer</summary>
val deleteAlbum : album:Album -> ctx:DbContext -> Unit

Full name: SuaveMusicStore.Db.deleteAlbum
val album : Album
member Common.SqlEntity.Delete : unit -> unit
SqlDataProvider<...>.dataContext.SubmitUpdates() : Unit


<summary>Save changes to data-source. May throws errors: To deal with non-saved items use GetUpdates() and ClearUpdates().</summary>
val getArtists : ctx:DbContext -> Artist list

Full name: SuaveMusicStore.Db.getArtists
property SqlDataProvider<...>.dataContext.publicSchema.Artists: SqlDataProvider<...>.dataContext.publicSchema.public.artists


<summary> The base table artists belonging to schema public</summary>
val createAlbum : artistId:int * genreId:int * price:decimal * title:string -> ctx:DbContext -> Unit

Full name: SuaveMusicStore.Db.createAlbum
val artistId : int
val genreId : int
val price : decimal
val title : string
SqlDataProvider<...>.dataContext.publicSchema.public.albums.Create() : SqlDataProvider<...>.dataContext.public.albumsEntity
SqlDataProvider<...>.dataContext.publicSchema.public.albums.Create(data: System.Collections.Generic.IEnumerable<string * obj>) : SqlDataProvider<...>.dataContext.public.albumsEntity


<summary>Item array of database columns:
artistid,genreid,price,title</summary>

SqlDataProvider<...>.dataContext.publicSchema.public.albums.Create(artistid: int, genreid: int, price: decimal, title: string) : SqlDataProvider<...>.dataContext.public.albumsEntity
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val updateAlbum : album:Album -> artistId:int * genreId:int * price:decimal * title:string -> ctx:DbContext -> Unit

Full name: SuaveMusicStore.Db.updateAlbum
property SqlDataProvider<...>.dataContext.public.albumsEntity.Artistid: int


<summary> integer</summary>
property SqlDataProvider<...>.dataContext.public.albumsEntity.Genreid: int


<summary> integer</summary>
property SqlDataProvider<...>.dataContext.public.albumsEntity.Price: decimal


<summary> numeric</summary>
property SqlDataProvider<...>.dataContext.public.albumsEntity.Title: string


<summary> character varying(160)</summary>
type IntPath = PrintfFormat<(int -> string),unit,string,string,int>

Full name: SuaveMusicStore.Path.IntPath
Multiple items
type PrintfFormat<'Printer,'State,'Residue,'Result> =
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>
member Value : string

Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_>

--------------------
type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> =
inherit PrintfFormat<'Printer,'State,'Residue,'Result>
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>

Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_,_>

--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>

--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>
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<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val withParam : key:string * value:string -> path:string -> string

Full name: SuaveMusicStore.Path.withParam
val key : string
val value : string
val path : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val home : string

Full name: SuaveMusicStore.Path.home
val overview : string

Full name: SuaveMusicStore.Path.Store.overview
val browse : string

Full name: SuaveMusicStore.Path.Store.browse
val details : IntPath

Full name: SuaveMusicStore.Path.Store.details
val browseKey : string

Full name: SuaveMusicStore.Path.Store.browseKey
module Admin

from SuaveMusicStore.Path
val manage : string

Full name: SuaveMusicStore.Path.Admin.manage
val createAlbum : string

Full name: SuaveMusicStore.Path.Admin.createAlbum
val editAlbum : IntPath

Full name: SuaveMusicStore.Path.Admin.editAlbum
val deleteAlbum : IntPath

Full name: SuaveMusicStore.Path.Admin.deleteAlbum
namespace Suave
module Form

from Suave
type Album =
{ArtistId: decimal;
GenreId: decimal;
Title: string;
Price: decimal;
ArtUrl: string;}

Full name: SuaveMusicStore.Form.Album
Album.ArtistId: decimal
Multiple items
val decimal : value:'T -> decimal (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.decimal

--------------------
type decimal = System.Decimal

Full name: Microsoft.FSharp.Core.decimal

--------------------
type decimal<'Measure> = decimal

Full name: Microsoft.FSharp.Core.decimal<_>
Album.GenreId: decimal
Album.Title: string
Album.Price: decimal
Album.ArtUrl: string
val album : Form<Album>

Full name: SuaveMusicStore.Form.album
Multiple items
union case Form.Form: FormProp<'a> list * ServerSideValidation<'a> list -> Form<'a>

--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list

Full name: Suave.Form.Form<_>
union case FormProp.TextProp: Property<'a,string> -> FormProp<'a>
val f : Album
val maxLength : max:int -> Validation<string>

Full name: Suave.Form.maxLength
union case FormProp.DecimalProp: Property<'a,decimal> -> FormProp<'a>
val min : min:decimal -> Validation<decimal>

Full name: Suave.Form.min
val max : max:decimal -> Validation<decimal>

Full name: Suave.Form.max
val step : step:System.Decimal -> Validation<decimal>

Full name: Suave.Form.step
module Html

from Suave
val em : s:string -> Node

Full name: SuaveMusicStore.View.em
val s : string
val tag : tag:string -> attr:Attribute list -> contents:Node list -> Node

Full name: Suave.Html.tag
union case Node.Text: string -> Node
val cssLink : href:string -> Node

Full name: SuaveMusicStore.View.cssLink
val href : string
val link : attr:Attribute list -> Node

Full name: Suave.Html.link
val h2 : s:string -> Node

Full name: SuaveMusicStore.View.h2
val ul : nodes:Node list -> Node

Full name: SuaveMusicStore.View.ul
val nodes : Node list
val li : (Node list -> Node)

Full name: SuaveMusicStore.View.li
val table : x:Node list -> Node

Full name: SuaveMusicStore.View.table
val x : Node list
val th : x:Node list -> Node

Full name: SuaveMusicStore.View.th
val tr : x:Node list -> Node

Full name: SuaveMusicStore.View.tr
val td : x:Node list -> Node

Full name: SuaveMusicStore.View.td
val strong : s:string -> Node

Full name: SuaveMusicStore.View.strong
val text : s:string -> Node list

Full name: Suave.Html.text
val form : x:Node list -> Node

Full name: SuaveMusicStore.View.form
val formInput : (('a -> Quotations.Expr<'b>) -> Attribute list -> Form<'a> -> Node)

Full name: SuaveMusicStore.View.formInput
val input : quotF:('a -> Quotations.Expr<'b>) -> attrs:Attribute list -> form:Form<'a> -> Node

Full name: Suave.Form.input
val submitInput : value:string -> Node

Full name: SuaveMusicStore.View.submitInput
val input : attr:Attribute list -> Node

Full name: Suave.Html.input
type Field<'a> =
{Label: string;
Html: Form<'a> -> Node;}

Full name: SuaveMusicStore.View.Field<_>
Field.Label: string
Multiple items
Field.Html: Form<'a> -> Node

--------------------
type HtmlAttribute = string * string

Full name: Suave.Form.HtmlAttribute
Multiple items
union case Form.Form: FormProp<'a> list * ServerSideValidation<'a> list -> Form<'a>

--------------------
module Form

from SuaveMusicStore

--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list

Full name: Suave.Form.Form<_>
type Node =
| Element of Element * Node list
| VoidElement of Element
| Text of string
| Raw of string
| WhiteSpace of string

Full name: Suave.Html.Node
type Fieldset<'a> =
{Legend: string;
Fields: Field<'a> list;}

Full name: SuaveMusicStore.View.Fieldset<_>
Fieldset.Legend: string
Fieldset.Fields: Field<'a> list
type FormLayout<'a> =
{Fieldsets: Fieldset<'a> list;
SubmitText: string;
Form: Form<'a>;}

Full name: SuaveMusicStore.View.FormLayout<_>
FormLayout.Fieldsets: Fieldset<'a> list
FormLayout.SubmitText: string
Multiple items
FormLayout.Form: Form<'a>

--------------------
module Form

from SuaveMusicStore

--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list

Full name: Suave.Form.Form<_>
val renderForm : layout:FormLayout<'a> -> Node

Full name: SuaveMusicStore.View.renderForm
val layout : FormLayout<'a>
val set : Fieldset<'a>
val field : Field<'a>
val div : (Attribute list -> Node list -> Node)

Full name: Suave.Html.div
Field.Html: Form<'a> -> Node
FormLayout.Form: Form<'a>
val home : Node list

Full name: SuaveMusicStore.View.home
val store : genres:string list -> Node list

Full name: SuaveMusicStore.View.store
val genres : string list
val p : (Attribute list -> Node list -> Node)

Full name: Suave.Html.p
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val length : list:'T list -> int

Full name: Microsoft.FSharp.Collections.List.length
val genre : string
val url : string
module Path

from SuaveMusicStore
module Store

from SuaveMusicStore.Path
val a : href:string -> attr:Attribute list -> (Node list -> Node)

Full name: Suave.Html.a
val browse : genre:string -> albums:Db.Album list -> Node list

Full name: SuaveMusicStore.View.browse
val albums : Db.Album list
module Db

from SuaveMusicStore
type Album = FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity

Full name: SuaveMusicStore.Db.Album
val album : Db.Album
val details : Path.IntPath

Full name: SuaveMusicStore.Path.Store.details
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Albumid: int


<summary> integer</summary>
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Title: string


<summary> character varying(160)</summary>
val details : album:Db.AlbumDetails -> Node list

Full name: SuaveMusicStore.View.details
val album : Db.AlbumDetails
type AlbumDetails = FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity

Full name: SuaveMusicStore.Db.AlbumDetails
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Title: string


<summary> character varying(160)</summary>
val img : attr:Attribute list -> Node

Full name: Suave.Html.img
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumarturl: string


<summary> character varying(1024)</summary>
val caption : string
val t : string
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Genre: string


<summary> character varying(120)</summary>
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Artist: string


<summary> character varying(120)</summary>
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Price: decimal


<summary> numeric</summary>
System.Decimal.ToString() : string
System.Decimal.ToString(provider: System.IFormatProvider) : string
System.Decimal.ToString(format: string) : string
System.Decimal.ToString(format: string, provider: System.IFormatProvider) : string
val truncate : k:int -> s:string -> string

Full name: SuaveMusicStore.View.truncate
val k : int
property System.String.Length: int
System.String.Substring(startIndex: int) : string
System.String.Substring(startIndex: int, length: int) : string
val manage : albums:Db.AlbumDetails list -> Node list

Full name: SuaveMusicStore.View.manage
val albums : Db.AlbumDetails list
val editAlbum : Path.IntPath

Full name: SuaveMusicStore.Path.Admin.editAlbum
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumid: int


<summary> integer</summary>
val deleteAlbum : Path.IntPath

Full name: SuaveMusicStore.Path.Admin.deleteAlbum
val deleteAlbum : albumTitle:string -> Node list

Full name: SuaveMusicStore.View.deleteAlbum
val albumTitle : string
val br : attr:Attribute list -> Node

Full name: Suave.Html.br
val createAlbum : genres:(decimal * string) list -> artists:(decimal * string) list -> Node list

Full name: SuaveMusicStore.View.createAlbum
val genres : (decimal * string) list
val artists : (decimal * string) list
val album : Form<Form.Album>

Full name: SuaveMusicStore.Form.album
type HtmlAttribute = string * string

Full name: Suave.Form.HtmlAttribute
val selectInput : quotF:('a -> Quotations.Expr<'b>) -> options:('b * string) list -> selected:'b option -> form:Form<'a> -> Node (requires equality)

Full name: Suave.Form.selectInput
val f : Form.Album
Form.Album.GenreId: decimal
union case Option.None: Option<'T>
Form.Album.ArtistId: decimal
Form.Album.Title: string
Form.Album.Price: decimal
Form.Album.ArtUrl: string
val editAlbum : album:Db.Album -> genres:(decimal * string) list -> artists:(decimal * string) list -> Node list

Full name: SuaveMusicStore.View.editAlbum
union case Option.Some: Value: 'T -> Option<'T>
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Genreid: int


<summary> integer</summary>
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Artistid: int


<summary> integer</summary>
val formatDec : d:System.Decimal -> string

Full name: Suave.Form.formatDec
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Price: decimal


<summary> numeric</summary>
val notFound : Node list

Full name: SuaveMusicStore.View.notFound
val index : container:Node list -> string

Full name: SuaveMusicStore.View.index
val container : Node list
val html : (Attribute list -> Node list -> Node)

Full name: Suave.Html.html
val head : (Attribute list -> Node list -> Node)

Full name: Suave.Html.head
val title : attr:Attribute list -> s:string -> Node

Full name: Suave.Html.title
val body : (Attribute list -> Node list -> Node)

Full name: Suave.Html.body
val htmlToString : node:Node -> string

Full name: Suave.Html.htmlToString
module App

from SuaveMusicStore
module Filters

from Suave
module Model

from Suave
module Binding

from Suave.Model
module Operators

from Suave
module RequestErrors

from Suave
module Successful

from Suave
module Web

from Suave
val html : container:Html.Node list -> WebPart

Full name: SuaveMusicStore.App.html
val container : Html.Node list
val OK : body:string -> WebPart

Full name: Suave.Successful.OK
module View

from SuaveMusicStore
val index : container:Html.Node list -> string

Full name: SuaveMusicStore.View.index
val browse : (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.App.browse
val request : apply:(HttpRequest -> HttpContext -> 'a) -> context:HttpContext -> 'a

Full name: Suave.Http.request
val r : HttpRequest
member HttpRequest.queryParam : key:string -> Choice<string,string>
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
val getContext : unit -> FSharp.Data.Sql.SqlDataProvider<...>.dataContext

Full name: SuaveMusicStore.Db.getContext
val getAlbumsForGenre : genreName:string -> ctx:Db.DbContext -> Db.Album list

Full name: SuaveMusicStore.Db.getAlbumsForGenre
val browse : genre:string -> albums:Db.Album list -> Html.Node list

Full name: SuaveMusicStore.View.browse
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
val msg : string
val BAD_REQUEST : body:string -> WebPart

Full name: Suave.RequestErrors.BAD_REQUEST
val overview : (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.App.overview
val warbler : f:('t -> 't -> 'u) -> 't -> 'u

Full name: Suave.WebPart.warbler
val getGenres : ctx:Db.DbContext -> Db.Genre list

Full name: SuaveMusicStore.Db.getGenres
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val g : Db.Genre
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.genresEntity.Name: string


<summary> character varying(120)</summary>
val store : genres:string list -> Html.Node list

Full name: SuaveMusicStore.View.store
val details : id:int -> WebPart

Full name: SuaveMusicStore.App.details
val getAlbumDetails : id:int -> ctx:Db.DbContext -> Db.AlbumDetails option

Full name: SuaveMusicStore.Db.getAlbumDetails
val details : album:Db.AlbumDetails -> Html.Node list

Full name: SuaveMusicStore.View.details
val never : WebPart<'a>

Full name: Suave.WebPart.never
val manage : (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.App.manage
val getAlbumsDetails : ctx:Db.DbContext -> Db.AlbumDetails list

Full name: SuaveMusicStore.Db.getAlbumsDetails
val manage : albums:Db.AlbumDetails list -> Html.Node list

Full name: SuaveMusicStore.View.manage
val bindToForm : form:Form<'a> -> handler:('a -> HttpContext -> Async<HttpContext option>) -> (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.App.bindToForm
val form : Form<'a>
val handler : ('a -> HttpContext -> Async<HttpContext option>)
val bindReq : f:(HttpRequest -> Choice<'b,'c>) -> fCont:('b -> HttpContext -> 'd) -> fErr:('c -> HttpContext -> 'd) -> (HttpContext -> 'd)

Full name: Suave.Model.Binding.bindReq
val bindForm : form:Form<'a> -> req:HttpRequest -> Choice<'a,string>

Full name: Suave.Form.bindForm
val createAlbum : WebPart<HttpContext>

Full name: SuaveMusicStore.App.createAlbum
val ctx : FSharp.Data.Sql.SqlDataProvider<...>.dataContext
val choose : options:WebPart<'a> list -> WebPart<'a>

Full name: Suave.WebPart.choose
val GET : WebPart

Full name: Suave.Filters.GET
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.genresEntity.Genreid: int


<summary> integer</summary>
val getArtists : ctx:Db.DbContext -> Db.Artist list

Full name: SuaveMusicStore.Db.getArtists
val g : Db.Artist
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.artistsEntity.Artistid: int


<summary> integer</summary>
property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.artistsEntity.Name: string


<summary> character varying(120)</summary>
val createAlbum : genres:(decimal * string) list -> artists:(decimal * string) list -> Html.Node list

Full name: SuaveMusicStore.View.createAlbum
val POST : WebPart

Full name: Suave.Filters.POST
Multiple items
union case Form.Form: FormProp<'a> list * ServerSideValidation<'a> list -> Form<'a>

--------------------
module Form

from Suave

--------------------
module Form

from SuaveMusicStore

--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list

Full name: Suave.Form.Form<_>
val form : Form.Album
val createAlbum : artistId:int * genreId:int * price:decimal * title:string -> ctx:Db.DbContext -> Unit

Full name: SuaveMusicStore.Db.createAlbum
module Redirection

from Suave
val FOUND : location:string -> WebPart

Full name: Suave.Redirection.FOUND
val editAlbum : id:int -> WebPart<HttpContext>

Full name: SuaveMusicStore.App.editAlbum
val getAlbum : id:int -> ctx:Db.DbContext -> Db.Album option

Full name: SuaveMusicStore.Db.getAlbum
val editAlbum : album:Db.Album -> genres:(decimal * string) list -> artists:(decimal * string) list -> Html.Node list

Full name: SuaveMusicStore.View.editAlbum
val updateAlbum : album:Db.Album -> artistId:int * genreId:int * price:decimal * title:string -> ctx:Db.DbContext -> Unit

Full name: SuaveMusicStore.Db.updateAlbum
val deleteAlbum : id:int -> WebPart<HttpContext>

Full name: SuaveMusicStore.App.deleteAlbum
val deleteAlbum : albumTitle:string -> Html.Node list

Full name: SuaveMusicStore.View.deleteAlbum
val deleteAlbum : album:Db.Album -> ctx:Db.DbContext -> Unit

Full name: SuaveMusicStore.Db.deleteAlbum
val webPart : WebPart<HttpContext>

Full name: SuaveMusicStore.App.webPart
val path : pathAfterDomain:string -> WebPart

Full name: Suave.Filters.path
val home : Html.Node list

Full name: SuaveMusicStore.View.home
val pathScan : pf:PrintfFormat<'a,'b,'c,'d,'t> -> h:('t -> WebPart) -> WebPart

Full name: Suave.Filters.pathScan
val pathRegex : pathAfterDomainRegex:string -> WebPart

Full name: Suave.Filters.pathRegex
module Files

from Suave
val browseHome : WebPart

Full name: Suave.Files.browseHome
val notFound : Html.Node list

Full name: SuaveMusicStore.View.notFound
val startWebServer : config:SuaveConfig -> webpart:WebPart -> unit

Full name: Suave.Web.startWebServer
val defaultConfig : SuaveConfig

Full name: Suave.Web.defaultConfig

Show code from this section on GitHub

results matching ""

    No results matching ""