SaturnFramework / Saturn

Opinionated, web development framework for F# which implements the server-side, functional MVC pattern
https://saturnframework.org
MIT License
715 stars 109 forks source link

Get WebHostEnvironment from CE extension #326

Open jkone27 opened 2 years ago

jkone27 commented 2 years ago

I am trying to have WebHostEnvironment during configure services, but i don't figure out how to do it.

if i do it in this "tricky way" i think the order of execution is preventing me from having WebHostEnvironment anyway.

i get a null reference exception, i guess because the middleware (IApplicationBuilder>> steps) are configured before the services (IServiceCollection>> steps)

Any working way in which i could get WebHostEnvironment in the service step ?

    type ApplicationBuilder with
    [<CustomOperationAttribute("acme_bootstrap")>]
    member this.AcmeBootstrap(state : ApplicationState) =

        let mutable environment : IWebHostEnvironment = null 

        let middleware (app : IApplicationBuilder) =
            environment <- Environment.getWebHostEnvironment(app)
            app

        let service (services : IServiceCollection) =
            services.BootstrapEndpointsWebApplication(
                environment,  /// breakes here with NULL REF EX as this is invoked before middleware setup i guess...
                (Config.getConfiguration(services)),
                fun opt ->
                    opt.ApplicationInformation.ApplicationName <- "Travix.WebApi.Template.ApplicationName"
                    opt.ApplicationInformation.ApplicationGroup <- "Travix.WebApi.Template.ApplicationGroup"
            )

        {  state with
            ServicesConfig = service::state.ServicesConfig
            AppConfigs = middleware::state.AppConfigs
            }
jkone27 commented 2 years ago

This is the workaround i had to use, a Static member, with a backing mutable field, which is populated in the pipeline

module SaturnExtensions =

    let mutable env : IWebHostEnvironment = null

    type ApplicationBuilder with

    static member StaticEnvironment
        with get() = env
        and set(v) = env <- v

so it's set earlier in configure webhost configuration step, and used in subsequent pipeline steps

webHostBuilder.ConfigureAppConfiguration(fun context config ->

                ApplicationBuilder.StaticEnvironment <- context.HostingEnvironment // ASSIGNED HERE

                !config.AddJsonFile("appsettings.json")
                    .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", true)
                    .AddEnvironmentVariables()
            )

for example i used it in this step (invoked later in my application builder


    [<CustomOperationAttribute("travix_bootstrap")>]
    member this.TravixBootstrap (state : ApplicationState) =

        let service (services : IServiceCollection) =

            services.BootstrapEndpointsWebApplication(
                ApplicationBuilder.StaticEnvironment, //<<<<<< USED HERE
                (Config.getConfiguration(services)),
                fun opt ->
                    opt.ApplicationInformation.ApplicationName <- "Travix.WebApi.Template.ApplicationName"
                    opt.ApplicationInformation.ApplicationGroup <- "Travix.WebApi.Template.ApplicationGroup"
            )

        {  state with
            ServicesConfig = service::state.ServicesConfig
            //AppConfigs = middleware::state.AppConfigs
            }