Quatro - Step 1
Having already made the leap to F#, we will now do our Hello World in Freya. This is adapted from the "Getting Started" article on their site.
First up, we'll attack project.json
. This one will require more modifications* than the others. Let's start
with the dependencies section:
1: 2: 3: 4: 5: 6: |
|
Freya should be self-explanatory, and we've seen the Owin and Kestrel imports before. The new one is the last one, and
this package provides fill-ins for some types that used to be defined in mscorlib
(the big library-to-rule-them-all
that went away between the full .NET framework and .NET Core).
The frameworks sections needs some attention as well:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: |
|
These imports allow us to use some Freya dependencies that target Portable Class Libraries (PCLs) that are supported by
.NET Core. Finally, while we're there, change "Program.fs" to "App.fs" in the compiled file list, as we'll rename
Program.fs
to App.fs
to remain consistent among the projects.
Now, for App.fs
:
1: 2: 3: 4: 5: 6: 7: |
|
Freya.Core
gives us the freya
computation expression, which we will use for the main part of our request handling.
Freya.Machines.Http
provides the freyaMachine
computation expression, which allows us to define our
request-response. Freya.Routers.Uri.Template
provides the freyaRouter
computation expression, where we assign an
HTTP machine to a URL route pattern.
Continuing on...
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: |
|
This code uses the three expressions described above to define the response (hard-coded for now), the machine that uses it for its OK response, and the route that uses the machine.
Still within module App =
...
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
This is the familiar Startup
class from Tres, except that the Configure()
method uses the Freya implementation
instead of the Nancy implementation. Notice that the middleware function uses the router as the hook into the
pipeline; that is how we get the OWIN request to be handled by Freya. Notice how much closer to idiomatic F# this code
has become; the only place we had to ignore
anything was the "seam" where we interoperated with the OWIN library.
dotnet run
should succeed at this point, and localhost:5000 should display our Hello World message.
* - Huge props go to @neoeinstein for documenting these settings in this Gist. I had not seen the PCL compat package or an import for "net452" in .NET Core before this.
module Freya
from Freya.Core.Inference
--------------------
module Freya
from Freya.Core
--------------------
namespace Freya
--------------------
type Freya<'a> = State -> Async<'a * State>
Full name: Freya.Core.Freya<_>
from Quatro
Full name: Quatro.App.hello
Full name: Freya.Core.Builder.freya
from Freya.Machines.Http
Full name: Freya.Machines.Http.Represent.text
Full name: Quatro.App.machine
Full name: Freya.Machines.Http.Builder.freyaMachine
Calls HttpMachineBuilder.HandleOk
Full name: Quatro.App.router
Full name: Freya.Routers.Uri.Template.Builder.freyaRouter
Calls UriTemplateRouterBuilder.Resource
type Startup =
new : unit -> Startup
member Configure : app:IApplicationBuilder -> unit
Full name: Quatro.App.Startup
--------------------
new : unit -> Startup
Full name: Quatro.App.Startup.Configure
member ApplicationServices : IServiceProvider with get, set
member Build : unit -> RequestDelegate
member New : unit -> IApplicationBuilder
member Properties : IDictionary<string, obj>
member ServerFeatures : IFeatureCollection
member Use : middleware:Func<RequestDelegate, RequestDelegate> -> IApplicationBuilder
Full name: Microsoft.AspNetCore.Builder.IApplicationBuilder
module OwinMidFunc
from Freya.Core
--------------------
type OwinMidFunc = System.Func<OwinAppFunc,OwinAppFunc>
Full name: Freya.Core.OwinMidFunc
Full name: Freya.Core.OwinMidFunc.ofFreya
union case UriTemplateRouter.UriTemplateRouter: (UriTemplateRoutes -> unit * UriTemplateRoutes) -> UriTemplateRouter
--------------------
module UriTemplateRouter
from Freya.Routers.Uri.Template
--------------------
type UriTemplateRouter =
| UriTemplateRouter of (UriTemplateRoutes -> unit * UriTemplateRoutes)
static member Freya : router:UriTemplateRouter -> Freya<PipelineChoice>
static member Pipeline : router:UriTemplateRouter -> Pipeline
Full name: Freya.Routers.Uri.Template.UriTemplateRouter
(extension) IApplicationBuilder.UseOwin(pipeline: System.Action<System.Action<System.Func<System.Func<System.Collections.Generic.IDictionary<string,obj>,System.Threading.Tasks.Task>,System.Func<System.Collections.Generic.IDictionary<string,obj>,System.Threading.Tasks.Task>>>>) : IApplicationBuilder
Full name: Microsoft.FSharp.Core.Operators.ignore
type EntryPointAttribute =
inherit Attribute
new : unit -> EntryPointAttribute
Full name: Microsoft.FSharp.Core.EntryPointAttribute
--------------------
new : unit -> EntryPointAttribute
Full name: Quatro.App.main
type WebHostBuilder =
new : unit -> WebHostBuilder
member Build : unit -> IWebHost
member ConfigureLogging : configureLogging:Action<ILoggerFactory> -> IWebHostBuilder
member ConfigureServices : configureServices:Action<IServiceCollection> -> IWebHostBuilder
member GetSetting : key:string -> string
member UseLoggerFactory : loggerFactory:ILoggerFactory -> IWebHostBuilder
member UseSetting : key:string * value:string -> IWebHostBuilder
Full name: Microsoft.AspNetCore.Hosting.WebHostBuilder
--------------------
WebHostBuilder() : unit
(extension) IWebHost.Run(token: System.Threading.CancellationToken) : unit