Skip to content

TanguyPa/inertia-aspcore

Repository files navigation

Attribution

This library is heavily inspired by Nothing-Works/inertia-aspnetcore and based on a fork of kapi2289/InertiaCore

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.

using InertiaCore.Extensions;

[...]

builder.Services.AddInertia();

[...]

app.UseInertia();

Usage

Frontend

Create a file /Views/App.cshtml.

@using InertiaCore
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title inertia>My App</title>
</head>
<body>
@await Inertia.Html(Model)

<script src="/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().

    public async Task<IActionResult> Index()
    {
        var posts = await _context.Posts.ToListAsync();
        
        var data = new
        {
            Posts = posts,
        };
        
        return Inertia.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]
    public async Task<IActionResult> Create([FromBody] Post post)
    {
        if (!ModelState.IsValid)
        {
            // The validation errors are passed automatically.
            return await Index();
        }
        
        _context.Add(post);
        await _context.SaveChangesAsync();
        
        return RedirectToAction("Index");
    }

Features

Shared data

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

using InertiaCore;

[...]

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

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>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title inertia>My App</title>
    
    @await Inertia.Head(Model)
</head>
<body>
@await Inertia.Html(Model)

<script src="/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.

using InertiaCore.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>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title inertia>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>

And here is the corresponding vite.config.js

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import laravel from "laravel-vite-plugin";
import path from "path";
import { mkdirSync } from "fs";

// Auto-initialize the default output directory
const outDir = "../wwwroot/build";

mkdirSync(outDir, { recursive: true });

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    laravel({
      input: ["src/main.tsx"],
      publicDirectory: outDir,
    }),
    react(),
  ],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
  build: {
    outDir,
    emptyOutDir: true,
  },
});

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

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

And here is the corresponding vite.config.js

import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
import laravel from "laravel-vite-plugin";
import path from "path";
import {mkdirSync} from "fs";

const outDir = "../wwwroot/build";

mkdirSync(outDir, {recursive: true});

export default defineConfig({
  plugins: [
    laravel({
      input: ["src/app.ts"],
      publicDirectory: outDir,
      refresh: true,
    }),
    vue({
      template: {
        transformAssetUrls: {
          base: null,
          includeAbsolute: false,
        },
      },
    }),
  ],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
  build: {
    outDir,
    emptyOutDir: true,
  },
});

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

@using InertiaCore
@using InertiaCore.Utils
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="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

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published