Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider supporting #r: "frameworkreference:" #9417

Open
cartermp opened this issue Jun 9, 2020 · 26 comments
Open

Consider supporting #r: "frameworkreference:" #9417

cartermp opened this issue Jun 9, 2020 · 26 comments

Comments

@cartermp
Copy link
Contributor

cartermp commented Jun 9, 2020

In F# 5, we'll have `#r "nuget:...". However, there are some first-party frameworks where this won't work:

  • ASP.NET Core
  • Windows Desktop

ASP.NET Core 2.x used is just a few NuGet packages, so it's possible to write an F# script that uses that to do some webby stuff. But if you want you use the latest ASP.NET Core, you need to magically know the closure of every assembly in the ASP.NET Core framework reference, reference those, and then use it. Horrible experience.

Also, the old school F# scripts that used to launch WinForms currently can't do this with .NET Core (on Windows). This is because WinForms and WPF both use the Windows Desktop framework reference, and an additional MSBuild property to tell the build system which additional references to pull in (UseWinForms and UseWPF). Both can be specified at the same time. We may want to have a think about what it would mean to support these.

tagging his majest, @KevinRansom

@KevinRansom
Copy link
Member

Agreed, I wonder what it would look like.

@cartermp
Copy link
Contributor Author

cartermp commented Jun 9, 2020

Perhaps:

#r "frameworkreference: aspnet"

#r "frameworkreference: windowsdesktop, usewinforms=true
#r "frameworkreference: windowsdesktop, usewpf=true
#r "frameworkreference: windowsdesktop, usewinforms=true, usewpf=true

?

@KevinRansom
Copy link
Member

KevinRansom commented Jun 9, 2020

So, if I understand the request it is to handle the dotnet framework packs that are distributed with the dotnet sdk.
Here:
image

It feels like in order for net5.0 apps to work dotnet build already knows how to do this, so perhaps it's merely a simple extension to #r "nuget: ..."

for example:
#r "nuget: Microsoft.AspNetCore.App.Ref, 5.0.0-preview.3.20214.2"
#r "nuget: Microsoft.WindowsDesktop.App.Ref, 5.0.0-preview.3.20214.2"

or perhaps:
#r "nuget: pack=Microsoft.WindowsDesktop.App.Ref, version=5.0.0-preview.3.20214.2"

And we use this to set the tfm for the build to the required tfm, not sure how the version maps yet. but I expect there are knobs.

What do you think?

@Krzysztof-Cieslak
Copy link
Contributor

Krzysztof-Cieslak commented Jun 9, 2020

It looks like this in the project file: https://github.com/SaturnFramework/Saturn/blob/master/src/Saturn/Saturn.fsproj#L28

So maybe #r "nuget: framework=Microsoft.AspNetCore.App" ?

edited: kcr, adding snippet

<snip>
  <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</snip>

@baronfel
Copy link
Member

baronfel commented Jun 9, 2020

FWIW @Krzysztof-Cieslak, you only need that framework reference because the SDK in the project file isn't set to the SDK for aspnetcore: "Microsoft.NET.Sdk.Web". If you did that the FrameworkReference would become redundant.

@baronfel
Copy link
Member

baronfel commented Jun 9, 2020

Similarly for the Windows Desktop stuff, if you use the matching SDK some set of the framework references are handled for you (based on those msbuild properties mentioned), so I wonder how much of this request is around framework references specifically, vs importing and using SDKs?

@KevinRansom
Copy link
Member

KevinRansom commented Jun 9, 2020

@baronfel , so it could also look like?

<Project Sdk="Microsoft.AspNetCore.App">

So #r "nuget: sdk=Microsoft.AspNetCore.App"
could also be in the frame?

I think I like @Krzysztof-Cieslak 's suggestion it's a bit crisper, and @cartermp has suggested there may be several, frameworkreference is a bit easier to read in the project file.

@baronfel
Copy link
Member

baronfel commented Jun 9, 2020

@KevinRansom

<Project Sdk="Microsoft.NET.Sdk.Web">
</Project>

Of course it would be too clear if the names matched up.

@KevinRansom
Copy link
Member

@baronfel , never underestimate our ability to evade clarity :-)

@cartermp
Copy link
Contributor Author

cartermp commented Jun 9, 2020

Yeah, having the names match up with the SDK names would be ideal. Is that something we'd considering keeping track of in the dependency manager? I highly doubt these names will change over time, since that would also mean that all visual studio tooling and SDK stuff would have to change as well.

@theundergroundsorcerer
Copy link

@cartermp
I am not sure whether it is related, but wrapping Forms calls into a dll, and then trying to use the dll from a script is not possible either. (There is no problem with other modules defined in the same dll).

@granicz
Copy link

granicz commented May 3, 2021

@cartermp Just putting this out here: https://twitter.com/mmwaikar/status/1388773735520292868

@jkone27
Copy link
Contributor

jkone27 commented Jan 21, 2022

would this also allow aspnetcore from fsx for example? :) would be awesome

@jkone27
Copy link
Contributor

jkone27 commented Feb 26, 2023

is there any workarounds atm to run aspnet from .fsx from net7/net8? @cartermp @vzarytovskii i think in here F# could possibly "shine" against compiled C# minimal api for it's simplicity ? resembling much python simplicity (or suave) but aspnet comes with many nice built-ins.. (e.g. ability to use Giraffe in fsx)

@vzarytovskii
Copy link
Member

is there any workarounds atm to run aspnet from .fsx from net7/net8? @cartermp @vzarytovskii i think in here F# could possibly "shine" against compiled C# minimal api for it's simplicity ? resembling much python simplicity (or suave) but aspnet comes with many nice built-ins.. (e.g. ability to use Giraffe in fsx)

I'm not aware of any.

Wondering if notebooks include it implicitly and can be used to run it @jonsequitur @colombod

@TheAngryByrd
Copy link
Contributor

TheAngryByrd commented Mar 6, 2023

I ended up with this as a workaround. This generates a set of scripts you can use with the #load directive. Depending on your sdk you may have to add to the blockedDlls list as it's not all inclusive.

With this I was able to get Giraffe running in FSI session.

#load "runtime-scripts/Microsoft.AspNetCore.App-7.0.3.fsx"

#r "nuget: Giraffe"


open System
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.Logging
open Microsoft.Extensions.DependencyInjection
open Giraffe

let webApp =
    choose [
        route "/ping"   >=> text "pong"
        route "/"       >=> htmlFile "/pages/index.html" ]

type Startup() =
    member __.ConfigureServices (services : IServiceCollection) =
        // Register default Giraffe dependencies
        services.AddGiraffe() |> ignore

    member __.Configure (app : IApplicationBuilder)
                        (env : IHostEnvironment)
                        (loggerFactory : ILoggerFactory) =
        // Add Giraffe to the ASP.NET Core pipeline
        app.UseGiraffe webApp


let main _ =
    Host.CreateDefaultBuilder()
        .ConfigureWebHostDefaults(
            fun webHostBuilder ->
                webHostBuilder
                    .UseStartup<Startup>()
                    |> ignore)
        .Build()
        .Run()

main ()

@jkone27
Copy link
Contributor

jkone27 commented Apr 12, 2023

@TheAngryByrd i tried your workaround generating the scripts folder as you suggested, it works!

if you have the below error the import is not correct (the error is misleading, maybe somethign to change in general for fsharp fsi when loading scripts.... i had this when i had and i didnt figure the error

#load "./folder/..."
/Users/admin/Repositories/scripts/testAspnetcoreWithGenScripts.fsx(25,57): error FS1141: Identifiers followed by '!' are reserved for future use

here is the working one! do not prepend ./ or / . cheers!

#load "runtime-scripts/Microsoft.AspNetCore.App-6.0.15.fsx"

open System
open Microsoft.AspNetCore.Builder

let builder = WebApplication.CreateBuilder()

let app = builder.Build()

let helloWorldHandler = System.Func<_>(fun () -> "Hello World!")
app.MapGet("/", helloWorldHandler)
app.Run()

@jkone27
Copy link
Contributor

jkone27 commented Apr 12, 2023

Also the script is a bit misleading, as i clearly have less than 25 lines of code, it points in the wrong portion of code (maybe due to load?)

@vzarytovskii
Copy link
Member

Also the script is a bit misleading, as i clearly have less than 25 lines of code, it points in the wrong portion of code (maybe due to load?)

#load will just "embed" it pretty much.

@jkone27
Copy link
Contributor

jkone27 commented Apr 12, 2023

loading with ./ caused that weird unclear user error

#load "./runtime-scripts/Microsoft.AspNetCore.App-6.0.15.fsx"

this version works, thanks a lot @TheAngryByrd !!!!

#load "runtime-scripts/Microsoft.AspNetCore.App-6.0.15.fsx"

@TheAngryByrd
Copy link
Contributor

I have a more refined version in IcedTasks where it also creates a load script per major version so it's a bit more "stable" when referencing and updating your runtimes.

@jkone27
Copy link
Contributor

jkone27 commented Jul 19, 2023

Hello, it seems in dotnet script they use this for framework reference, maybe it could be a great idea to reuse that same syntax if possible?

#r "sdk:Microsoft.NET.Sdk.Web"

https://github.com/dotnet-script/dotnet-script#specifying-an-sdk

@jkone27
Copy link
Contributor

jkone27 commented Mar 4, 2024

Hello, news on this topic, is it on roadmap for F#9 ? have a great day!

@vzarytovskii
Copy link
Member

Hello, news on this topic, is it on roadmap for F#9 ? have a great day!

It is not

@jkone27
Copy link
Contributor

jkone27 commented Oct 11, 2024

@cartermp @TheAngryByrd any news/suggestions on this topic, what would it take potentially to add a new #sdk: Microsoft.NET.Web.Sdk keyword and add it on top of script to modify the generation of the base hidden .fsproj file for dotnet fsi?
i think for how .NET is evolving in general, sdk support for dotnet fsi would be huge and i think beginners would love it too ! thank you for all the amazing work done for F# 9 !

@jkone27
Copy link
Contributor

jkone27 commented Oct 11, 2024

reporting this for context if anyone else want to try (add this to dotnet fsi) this as @baronfel provided some extra info, thanks a lot!

in . NET 8 MSBuild added a way to call a target and get data out of MSBuild 
in a structured JSON format that could be used to power tooling experiences, 
and that's what I'd suggest FSI try to do here

A lot of the patterns you'd need are already in FSI - 
if you're interested in this take a look at how the #r NuGet stuff is implemented

Essentially you
Create a fake project file
Call MSBuild commands on it
Do something with the results of those commands

In this case the command you'd run would be something like 

'dotnet msbuild -t: ProcessFrameworkReferences --getTargetResult:ProcessFrameworkReferences'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: New
Development

No branches or pull requests

9 participants