![]() |
VOOZH | about |
dotnet add package Suave.Dynamic --version 1.6.0
NuGet\Install-Package Suave.Dynamic -Version 1.6.0
<PackageReference Include="Suave.Dynamic" Version="1.6.0" />
<PackageVersion Include="Suave.Dynamic" Version="1.6.0" />Directory.Packages.props
<PackageReference Include="Suave.Dynamic" />Project file
paket add Suave.Dynamic --version 1.6.0
#r "nuget: Suave.Dynamic, 1.6.0"
#:package Suave.Dynamic@1.6.0
#addin nuget:?package=Suave.Dynamic&version=1.6.0Install as a Cake Addin
#tool nuget:?package=Suave.Dynamic&version=1.6.0Install as a Cake Tool
Suave.Dynamic is a Suave web part that can load other web parts dynamically and then route requests to them. This allows a single Suave web server to host multiple independent apps, each of which acts as the root of its own virtual directory.
Let's build a simple web part that can say "hello" and "goodbye":
module WebPart1
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
let app =
GET >=>
choose [
path "/hello" >=> OK $"Hello 1"
path "/goodbye" >=> OK $"Goodbye 1"
]
In another project, we can have a second, independent web part that behaves slightly differently:
module WebPart2
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
let app =
GET >=>
choose [
path "/hello" >=> OK $"Hello 2"
path "/goodbye" >=> OK $"Goodbye 2"
]
Now we need a basic Suave web server that hosts the web parts:
open Suave
open Suave.Filters
open Suave.Logging
open Suave.Operators
let app =
let logger = Targets.create LogLevel.Info [||]
choose [
Dynamic.WebPart.fromToml "WebParts.toml"
RequestErrors.NOT_FOUND "Found no handlers."
] >=> logWithLevelStructured
LogLevel.Info
logger
logFormatStructured
startWebServer defaultConfig app
The key line is:
Dynamic.WebPart.fromToml "WebParts.toml"
This loads the dynamic web parts using the information in a TOML configuration file:
[web_part.one]
assembly_path = '..\..\..\..\TestWebPart1\bin\Debug\net10.0\TestWebPart1.dll'
web_path = "/one"
[web_part.two]
assembly_path = '..\..\..\..\TestWebPart2\bin\Debug\net10.0\TestWebPart2.dll'
web_path = "/two"
type_full_name = "WebPart2"
property_name = "app"
The configuration file tells Suave.Dynamic where to find the dynamic web parts:
assembly_path: File path of assembly that contains the dynamic web partweb_path: Name of the virtual directory that will route to the dynamic web parttype_full_name (optional): Name of the type (or F# module) that contains the dynamic web partproperty_name (optional): Name of the type's static property that contains the dynamic web partIf type_full_name or property_name are omitted, Suave.Dynamic will search the assembly for a type that contains a static property of type WebPart.
We can then start the web server and browse to a URL such as http://localhost:8080/one/hello. The response is "Hello 1", as expected. Note, however, that the request that WebPart1 sees is just /hello, rather than /one/hello. This allows WebPart2 to be loaded as well, and respond to requests at /two/hello, without any conflict between the two web parts.
Dynamic web parts must be built carefully, so they can be successfully loaded at runtime. This requires the .fsproj file to contain the following settings:
EnableDynamicLoading to true. This copies all of the project's dependencies to its build directory.ExcludeAssets to runtime for both Suave and FSharp.Core. This prevents those particular assemblies from being copied to the build directory, and being loaded incompatibly by Suave.Dynamic.A typical .fsproj file for a dynamic web part will then look something like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EnableDynamicLoading>true</EnableDynamicLoading>
<SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>
</PropertyGroup>
<ItemGroup>
<Compile Include="WebPart.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MathNet.Numerics.FSharp" Version="5.0.0" />
<PackageReference Include="Suave" Version="2.6.2">
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
<PackageReference Update="FSharp.Core">
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</Project>
See the article Create a .NET Core application with plugins for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.