Suave.Razor is a library that provides support for Razor views to the Suave web server framework. It enables you to use the powerful Razor templating engine with your F# Suave web applications.
- 🎨 Razor Templates - Use
.cshtmlfiles with full Razor syntax support - 🔄 Auto-reload - Template changes are automatically detected and reloaded
- 🌍 Localization - Built-in support for localized views based on Accept-Language headers
- 📦 Layouts - Support for layout pages and sections
- đź’ľ In-Memory Compilation - Templates are compiled in memory for better performance
- 🔍 View Resolution - Intelligent view resolution with path-based lookups
Add the Suave.Razor package to your project using the .NET CLI:
dotnet add package Suave.RazorOr using Package Manager:
Install-Package Suave.RazorCreate a Views folder in your project and add a Razor view file hello.cshtml:
@model MyApp.Model
<h1>Hello @Model.Name!</h1>
<p>Welcome to Suave.Razor</p>type Model = { Name : string }open Suave
open Suave.Filters
open Suave.Operators
open Suave.Razor
let app =
choose [
path "/hello" >=> razor "hello" { Name = "World" }
RequestErrors.NOT_FOUND "Page not found"
]
startWebServer defaultConfig appThat's it! Navigate to http://localhost:8080/hello to see your rendered view.
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Razor
type Person = { Name : string; Age : int }
let app =
choose [
path "/" >=> razor "index" { Name = "Alice"; Age = 30 }
]
startWebServer defaultConfig appViews/index.cshtml:
@model Person
<html>
<head><title>Person Info</title></head>
<body>
<h1>@Model.Name</h1>
<p>Age: @Model.Age</p>
</body>
</html>Create a layout file to share common structure across multiple views.
Views/layout.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<title>@ViewBag.Title</title>
<meta charset="utf-8" />
@RenderSection("Styles", required: false)
</head>
<body>
<header>
<h1>My Suave App</h1>
</header>
<main>
@RenderBody()
</main>
<footer>
<p>© 2025 My Application</p>
</footer>
@RenderSection("Scripts", required: false)
</body>
</html>Views/page.cshtml:
@model MyModel
@{
Layout = "layout.cshtml";
ViewBag.Title = "My Page";
}
@section Styles {
<link rel="stylesheet" href="/css/page-specific.css" />
}
<div>
<h2>Page Content</h2>
<p>@Model.Content</p>
</div>
@section Scripts {
<script src="/js/page-specific.js"></script>
}F# Code:
type Entry = { Name : string; Age : int }
type DataModel = {
Title : string
Items : Entry list
}
let app =
path "/people" >=> razor "people" {
Title = "People List"
Items = [
{ Name = "Alice"; Age = 30 }
{ Name = "Bob"; Age = 25 }
{ Name = "Charlie"; Age = 35 }
]
}Views/people.cshtml:
@model DataModel
<h1>@Model.Title</h1>
<ul>
@foreach (var item in Model.Items)
{
<li>@item.Name (Age: @item.Age)</li>
}
</ul>The HTTP context is available through the ViewBag in your Razor views:
@{
var context = ViewBag.HttpContext;
var url = context.request.url;
}
<p>Current path: @url.AbsolutePath</p>Create a _ViewImports.cshtml file in your Views folder to add common @using statements:
Views/_ViewImports.cshtml:
@using System
@using System.Linq
@using System.Collections.GenericSuave.Razor automatically supports localized views based on the Accept-Language header. Views are resolved in the following order:
ViewName-{culture}.cshtml(e.g.,home-en-US.cshtml)ViewName.cshtml(fallback to default view)
Example:
Views/home.cshtml- Default viewViews/home-es-ES.cshtml- Spanish (Spain) versionViews/home-fr-FR.cshtml- French (France) version
The appropriate view will be automatically selected based on the client's language preferences.
Views are resolved in the following order:
- Relative to the current request path (e.g., for
/admin/users, checks/Views/admin/users.cshtml) - In parent directories up to the root
- In the root Views directory
- In the application root directory
This allows for flexible view organization and path-based overrides.
By default, views are resolved relative to the Suave homeDirectory configuration:
let config = {
defaultConfig with
homeDirectory = Some "/path/to/your/app"
}
startWebServer config appViews should be placed in a Views subfolder within the home directory.
Creates a WebPart that renders a Razor view with the specified model.
Parameters:
path- The name of the view file (without.cshtmlextension)model- The model object to pass to the view
Returns:
- A
WebPartthat renders the view with the model
Example:
path "/user" >=> razor "userProfile" { UserId = 123; UserName = "Alice" }Templates are automatically cached and invalidated when the source file changes. This provides optimal performance while allowing for rapid development with auto-reload.
By default, Razor templates are compiled in memory rather than written to temporary files. This improves performance and reduces disk I/O.
- .NET 10.0 or later
- Suave 3.2.1 or later
The Suave.Razor.Tests project in this repository contains a working example application demonstrating various features:
- Basic views
- Layout pages
- Sections
- Lists and data binding
- MVC Grid integration
To run the example:
cd Suave.Razor.Tests
dotnet runThen open your browser to http://localhost:8080/test1 to see the examples in action.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Copyright 2020 Ademar Gonzalez and contributors
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.