Setting up WebSharper in ASP.NET Core
To integrate WebSharper into your web application, use the WebSharper.AspNetCore nuget package. This documentation is for WebSharper version 9.1.3 and above.
Configuring options and startup
Configuring an ASP.NET Core application has two distinct stages: first setting up services and then the application pipeline. WebSharper relies on some services to run.
- Call
builder.Services.AddWebSharper()to set up required singleton service (orservices.AddWebSharper()in theConfigureServicesmethod of yourStartupclass for older versions of ASP.NET Core). It can take an optional action to set properties of theWebSharperOptionsobject, these are:DefaultAssembly: The assembly to load runtime metadata from to run WebSharper sitelets and remoting. Defaults to the entry assembly.AuthenticationScheme: The authentication scheme to use for WebSharper's built-in cookie authentication. Defaults to"WebSharper".Configuration: AnIConfigurationobject accessible from WebSharperContext. Defaults to the"websharper"section of the mainIConfigurationinstance available (usually loaded fromappsettings.jsonby Kestrel defaults).ContentRootPath: The content root path used by WebSharper. Defaults to theContentRootPathfrom theIHostingEnvironmentinstance.WebRootPath: The web root path used by WebSharper. Defaults to theWebRootPathfrom theIHostingEnvironmentinstance.
- Call
builder.Services.AddWebSharperServices()for the same setup, the difference is that it returns a builder for additional WebSharper service helpers. These are:.AddRemotingHandler<THandler>()to register a WebSharper remoting handler for instance-based remoting. This is a typed, service-level alternative toWebSharper.Core.Remoting.AddHandler. This method has 3 overloads, you can pass it a single type argument which will be instantiated, two type arguments where the first is the type of the handler and the second is the type of the implementation class, or one type argument and pass it an instance of that type..AddMvc()registers a scoped service to allow embedding WebSharper content into Razor pages..AddSiteletRef(siteletRef)registers aref<Sitelet<'T>>to serve as a fallback if no static sitelet value is configured in the pipeline. This can be used to make a site where the sitelet is expanded dynamically..AddRuntimeRef(runtimeRef)registers a reference to all objects needed for the WebSharper runtime, these are the sitelet value, runtime metadata, dependency graph, json serializer, and remoting server. This can be used to make fully dynamic WebSharper servers.
Additionally, these are the services you can directly configure with .AddSingleton or .AddScoped, overriding the defaults set by AddWebSharper/AddWebSharperServices:
IOptions<WebSharperOptions>: another way to access and configure theWebSharperOptionsobject.IWebSharperSiteletService: provides a sitelet to serve as a fallback if no static instance is configured in the middleware. It is not set by default.IWebSharperMetadataService: provides WebSharper runtime metadata (for example used for looking up sitelet bundles, remote functions, rendering page initialization code).IWebSharperRemotingServerService: provides the WebSharper remoting server.IWebSharperJsonProviderService: provides the WebSharper json serializer.ILogger<WebSharperInitializationService>: the logger used by WebSharper initialization.ILogger<WebSharperSiteletMiddleware>: the logger used by sitelets runtime.
Next are the middleware to put in the application pipeline.
WebSharper has two main middleware, one is for serving pages (sitelets), and the other for API endpoints generated for automatic remoting.
Configuring the pipeline
- Add
app.UseWebSharper()for a basic setup of both remoting and sitelets if configured. It has a builder parameter that can be used for additional configuration:Sitetetpasses a sitelet instance to server.DiscoverSiteletlooks for a class property with the[<Website>]attribute to obtain the sitelet instance. This is now deprecated.UseSitelets(false)turns off serving a sitelet entirely.UseSitelets(true)has no effect, it's the default.UseRemoting(false)turns off using remoting entirely.UseRemoting(true, headers)can be used to define additional headers to return.Useregisters an additional action will get the instance ofIWebSharperInitializationService.Loggeradds a logger for WebSharper startup, default to the discoverableILogger<IWebSharperService>service. Alternatively you can also pass it anILoggerFactory.
- The following options are also available in the builder, but usually not necessary to override defaults:
SiteletAssemblyspecifies which assembly contains the runtime metadata, defaults to the calling assembly having the startup code.
- Add
app.UseWebSharperRemotingas a shortcut to use remoting only. It also allows to define additional headers to return as a shortcut to using the builder. - Add
app.UseWebSharperSiteletsas a shortcut to use sitelets only. - Add
app.UseWebSharperScriptRedirectto set up script redirection to a localhost server. If thestartViteparameter is set totrue, it starts upvitein a separate console window for local debugging. TheredirectUrlRootargument defines the local url to use, defaults to thewebsharper:DebugScriptRedirectUrlsetting from config.
Serving JavaScript files
If you have any client-side code, then it will need access to compiled JavaScript files, which the WebSharper middleware does not provide. So you need to add the default static files provider app.UseStaticFiles().
Note that UseStaticFiles should be called after UseWebSharper. This way, WebSharper sitelets and remoting have a chance to handle requests even if they also happen to match a static file.
Authentication
To use WebSharper's user sessions, add this to your service configuration:
and also app.UseAuthentication() to your application pipeline.
If you configured a different authentication scheme in UseWebSharper, then you need to use that same scheme name here instead of "WebSharper".
Integrations
Return WebSharper content from an MVC controller
Use the .ToIActionResult() extension method available in the WebSharper.AspNetCore namespace to convert WebSharper content into a response object that ASP.NET Core can handle. For example:
Embed WebSharper controls into Razor pages
Remember to add required service with builder.Services.AddWebSharperServices().AddMvc(). Then, add a placeholder for WebSharper-generated startup script in your layout page:
Then in your Razor PageModel file (code backend), use the IWebSharperMvcService service with dependency injection, and then you can create a property that defines a WebSharper content embedded into the page. Here with also creating a named optimized bundle for the page:
Use this property within your page, like @Model.MyWebSharperControl. Do not create WebSharper.Web.Controls directly in your Razor expressions as the WebSharper compiler cannot discover them there for preprocessing.
For a small working example, check out https://github.com/dotnet-websharper/aspnetmvc
Middleware for Giraffe/Saturn
WebSharper.AspNetCore comes with two helpers to create http handlers for Giraffe/Saturn, these are Sitelets.HttpHandler(sitelet) and Remoting.HttpHandler().
Use them like this in Giraffe: