ASP.NET Core Integration Guide
Lune is an excellent choice for ASP.NET developers who want a lightweight way to add interactivity to their Razor views or pages without using a full-blown SPA.
Installation
Add Lune to your _Layout.cshtml file.
<!-- Views/Shared/_Layout.cshtml -->
<head>
<script src="https://cdn.jsdelivr.net/npm/lune-js" defer init></script>
</head>Data Injection
Serializing C# objects to JSON and injecting them into your Razor views is simple using JsonSerializer.
In your Controller:
public IActionResult Profile()
{
var userData = new {
Username = User.Identity.Name,
IsPremium = true,
LastLogin = DateTime.Now
};
ViewBag.UserJson = System.Text.Json.JsonSerializer.Serialize(userData);
return View();
}In your Razor View:
Use @Html.Raw() to output the JSON string directly into lu-scope.
<div lu-scope="@Html.Raw(ViewBag.UserJson)">
<p>Welcome, {{ Username }}</p>
<p lu-if="IsPremium">You are a premium member!</p>
</div>Antiforgery Tokens (CSRF)
ASP.NET Core requires an antiforgery token for POST/PUT/DELETE requests.
Option 1: Reading from Meta Tag
Add a meta tag with the antiforgery token to your _Layout.cshtml:
<meta name="X-XSRF-TOKEN" content="@Html.AntiForgeryToken()" />Then access it in your Lune methods:
function saveData() {
const token = document.querySelector('meta[name="X-XSRF-TOKEN"]').content;
fetch("/api/save/", {
method: "POST",
headers: {
RequestVerificationToken: token,
"Content-Type": "application/json"
},
body: JSON.stringify(this.formData)
});
}Practical Examples
1. Progressive Form Validation
Enhance your ASP.NET forms with real-time validation.
<script type="module">
import { createApp } from "lune-js";
function UsernameForm() {
return {
username: "",
get isValid() {
return this.username.length >= 5;
}
};
}
createApp({ UsernameForm }).mount();
</script>
<form method="post" lu-scope="UsernameForm()">
@Html.AntiForgeryToken()
<input type="text" name="Username" lu-model="username" />
<span lu-show="username && !isValid" class="text-danger"> Username must be at least 5 characters. </span>
<button :disabled="!isValid" type="submit">Submit</button>
</form>TIP
Derived values such as isValid live in a factory function: an object literal written inside lu-scope holds data only, so getters and methods go in JavaScript.
2. Dynamic Table Row Addition
Easily manage dynamic form sections where users can add or remove items.
<div
lu-scope="{
items: [{ description: '', amount: 0 }]
}"
>
<table class="table">
<tr lu-for="(item, index) in items">
<td><input type="text" :name="'Items[' + index + '].Description'" lu-model="item.description" /></td>
<td><input type="number" :name="'Items[' + index + '].Amount'" lu-model="item.amount" /></td>
<td><button type="button" @click="items.splice(index, 1)">Remove</button></td>
</tr>
</table>
<button type="button" @click="items.push({ description: '', amount: 0 })">Add Row</button>
</div>Handling Razor Conflicts
Razor uses the @ symbol, which Lune also uses for its event shorthand (@click).
Escaping @
You can escape the @ symbol in your Razor views by using @@.
<button @@click="increment">+</button>Changing Lune Delimiters
If you'd like to use different delimiters to avoid confusion with Razor:
createApp({
$delimiters: ["[[", "]]"]
}).mount();Razor View:
<p>[[ my_data_from_server ]]</p>