Consider supporting #r: "frameworkreference:"
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
Agreed, I wonder what it would look like.
Perhaps:
#r "frameworkreference: aspnet"
#r "frameworkreference: windowsdesktop, usewinforms=true
#r "frameworkreference: windowsdesktop, usewpf=true
#r "frameworkreference: windowsdesktop, usewinforms=true, usewpf=true
?
So, if I understand the request it is to handle the dotnet framework packs that are distributed with the dotnet sdk.
Here:

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?
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>
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.
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?
@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.
@KevinRansom
<Project Sdk="Microsoft.NET.Sdk.Web">
</Project>
Of course it would be too clear if the names matched up.
@baronfel , never underestimate our ability to evade clarity :-)
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.
@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).
@cartermp Just putting this out here: https://twitter.com/mmwaikar/status/1388773735520292868
would this also allow aspnetcore from fsx for example? :) would be awesome
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)
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
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 ()
@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()
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?)
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.
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"
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.
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
Hello, news on this topic, is it on roadmap for F#9 ? have a great day!
Hello, news on this topic, is it on roadmap for F#9 ? have a great day!
It is not
@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 !
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!
- https://learn.microsoft.com/en-us/visualstudio/msbuild/evaluate-items-and-properties?view=vs-2022
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'