- 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.
You can check out these examples to have some starting point for your new application.
- Using Package Manager:
PM> Install-Package AspNetCore.InertiaCore - Using .NET CLI:
dotnet add package AspNetCore.InertiaCore
You need to add few lines to the Program.cs or Starup.cs file.
usingInertiaCore.Extensions;[...]builder.Services.AddInertia();[...]app.UseInertia();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";});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");}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}});});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);}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});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";});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>