Skip to content

Repository files navigation

Inertia.js ASP.NET Adapter

NuGetBuildNuGetLicense

Features

  • Validation error handling.
  • Shared data.
  • Partial and async lazy props.
  • Server-side rendering.
  • Vite helper.
  • Cycle-safe model with relations data serialization.
  • Properly working PATCH, PUT and DELETE redirections.

Table of contents

Examples

You can check out these examples to have some starting point for your new application.

Installation

  1. Using Package Manager: PM> Install-Package AspNetCore.InertiaCore
  2. Using .NET CLI: dotnet add package AspNetCore.InertiaCore

Getting started

You need to add few lines to the Program.cs or Starup.cs file.

usingInertiaCore.Extensions;[...]builder.Services.AddInertia();[...]app.UseInertia();

Usage

Frontend

Create a file /Views/App.cshtml.

@using InertiaCore
<!DOCTYPE html><html><head><metacharset="utf-8"/><metaname="viewport" content="width=device-width, initial-scale=1.0"/><titleinertia>My App</title></head><body>
@await Inertia.Html(Model)
<scriptsrc="/js/app.js"></script></body></html>

You can change the root view file using:

builder.Services.AddInertia(options =>{options.RootView="~/Views/Main.cshtml";});

Backend

To pass data to a page component, use Inertia.Render().

publicasyncTask<IActionResult>Index(){varposts=await_context.Posts.ToListAsync();vardata=new{Posts=posts,};returnInertia.Render("Posts",data);}

To make a form endpoint, remember to add [FromBody] to your model parameter, because the request data is passed using JSON.

[HttpPost]publicasyncTask<IActionResult>Create([FromBody]Postpost){if(!ModelState.IsValid){// The validation errors are passed automatically.returnawaitIndex();}_context.Add(post);await_context.SaveChangesAsync();returnRedirectToAction("Index");}

Features

Shared data

You can add some shared data to your views using for example middlewares:

usingInertiaCore;[...]app.Use(async(context,next)=>{varuserId=context.Session.GetInt32("userId");Inertia.Share("auth",new{UserId=userId});// OrInertia.Share(newDictionary<string,object?>{["auth"]=>new{UserId=userId}});});

Async Lazy Props

You can use async lazy props to load data asynchronously in your components. This is useful for loading data that is not needed for the initial render of the page.

// simply use the LazyProps the same way you normally would, except pass in an async functionpublicasyncTask<IActionResult>Index(){varposts=newLazyProp(async()=>await_context.Posts.ToListAsync());vardata=new{Posts=posts,};returnInertia.Render("Posts",data);}

Server-side rendering

If you want to enable SSR in your Inertia app, remember to add Inertia.Head() to your layout:

@using InertiaCore
<!DOCTYPE html><html><head><metacharset="utf-8"/><metaname="viewport" content="width=device-width, initial-scale=1.0"/><titleinertia>My App</title>
@await Inertia.Head(Model)
</head><body>
@await Inertia.Html(Model)
<scriptsrc="/js/app.js"></script></body></html>

and enable the SSR option:

builder.Services.AddInertia(options =>{options.SsrEnabled=true;// You can optionally set a different URL than the default.options.SsrUrl="http://127.0.0.1:13714/render";// default});

Vite Helper

A Vite helper class is available to automatically load your generated styles or scripts by simply using the @Vite.Input("src/main.tsx") helper. You can also enable HMR when using React by using the @Vite.ReactRefresh() helper. This pairs well with the laravel-vite-plugin npm package.

To get started with the Vite Helper, you will need to add one more line to the Program.cs or Starup.cs file.

usingInertiaCore.Extensions;[...]builder.Services.AddViteHelper();// Or with options (default values shown)builder.Services.AddViteHelper(options =>{options.PublicDirectory="wwwroot";options.BuildDirectory="build";options.HotFile="hot";options.ManifestFilename="manifest.json";});

Examples


Here's an example for a TypeScript React app with HMR:

@using InertiaCore
@using InertiaCore.Utils
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport" content="width=device-width, initial-scale=1.0" /><titleinertia>My App</title></head><body>
@* This has to go first, otherwise preamble error *@
@Vite.ReactRefresh()
@await Inertia.Html(Model)
@Vite.Input("src/main.tsx")
</body></html>

with the corresponding vite.config.js, which is recommended to create in the ClientApp directory:

import{defineConfig}from"vite";importreactfrom"@vitejs/plugin-react";importlaravelfrom"laravel-vite-plugin";// https://vitejs.dev/config/exportdefaultdefineConfig({plugins: [laravel({input: ["src/main.tsx"],publicDirectory: "../wwwroot/",}),react(),],build: {emptyOutDir: true,},});

Here's an example for a TypeScript Vue app with Hot Reload:

@using InertiaCore
@using InertiaCore.Utils
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport" content="width=device-width, initial-scale=1.0" /><titleinertia>My App</title></head><body>
@await Inertia.Html(Model)
@Vite.Input("src/app.ts")
</body></html>

with the corresponding vite.config.js, which is recommended to create in the ClientApp directory:

import{defineConfig}from'vite';importvuefrom'@vitejs/plugin-vue';importlaravelfrom"laravel-vite-plugin";exportdefaultdefineConfig({plugins: [laravel({input: ["src/app.ts"],publicDirectory: "../wwwroot/",refresh: true,}),vue({template: {transformAssetUrls: {base: null,includeAbsolute: false,},},}),],build: {emptyOutDir: true,},});

Here's an example that just produces a single CSS file:

@using InertiaCore
@using InertiaCore.Utils
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport" content="width=device-width, initial-scale=1.0" /></head><body>
@await Inertia.Html(Model)
@Vite.Input("src/main.scss")
</body></html>

About

Inertia.js ASP.NET Adapter.

Topics

Resources

Stars

155 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages