{"id":15723236,"url":"https://github.com/mergehez/inertianetcore","last_synced_at":"2025-04-23T07:39:00.268Z","repository":{"id":257805698,"uuid":"865653180","full_name":"mergehez/InertiaNetCore","owner":"mergehez","description":"Inertia.js ASP.NET Core Adapter","archived":false,"fork":false,"pushed_at":"2025-02-04T19:33:04.000Z","size":337,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-06T10:42:51.201Z","etag":null,"topics":["adapter","asp-net-core","csharp","dotnet","frontend","inertia","inertiajs","reactjs","vue"],"latest_commit_sha":null,"homepage":"https://inertianetcore-d5c7hcggg7afdqg0.germanywestcentral-01.azurewebsites.net/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mergehez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-30T22:23:48.000Z","updated_at":"2025-03-05T10:53:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"5b895f0a-d61c-4983-b58d-c3f910107c04","html_url":"https://github.com/mergehez/InertiaNetCore","commit_stats":null,"previous_names":["mergehez/inertianetcore"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mergehez%2FInertiaNetCore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mergehez%2FInertiaNetCore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mergehez%2FInertiaNetCore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mergehez%2FInertiaNetCore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mergehez","download_url":"https://codeload.github.com/mergehez/InertiaNetCore/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250394108,"owners_count":21423360,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adapter","asp-net-core","csharp","dotnet","frontend","inertia","inertiajs","reactjs","vue"],"created_at":"2024-10-03T22:10:45.444Z","updated_at":"2025-04-23T07:39:00.243Z","avatar_url":"https://github.com/mergehez.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Inertia.js ASP.NET Core Adapter\n\n[![NuGet](https://img.shields.io/nuget/v/InertiaNetCore?style=flat-square\u0026color=blue)](https://www.nuget.org/packages/InertiaNetCore)\n[![NuGet](https://img.shields.io/nuget/dt/InertiaNetCore?style=flat-square\u0026color=blue)](https://www.nuget.org/packages/InertiaNetCore)\n[![License](https://img.shields.io/github/license/mergehez/InertiaNetCore?style=flat-square\u0026color=blue)](https://github.com/mergehez/InertiaNetCore/blob/main/LICENSE)\n\nThis library is a fork of [kapi2289/InertiaCore](https://github.com/kapi2289/InertiaCore). (Last commit: Aug 18, 2023)\n\nSome errors were fixed, and unnecessary dependencies were removed. The library will be maintained and updated whenever necessary.\n\nIt is compatible with .NET 7, .NET 8, and .NET 9.\n\nFeel free to contribute to the project by creating issues or pull requests.\n\n## Table of contents\n\n- [Demo](#demo)\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Configuration](#configuration)\n- [Features](#features)\n  * [Shared data](#shared-data)\n  * [Flash Messages](#flash-messages)\n  * [Deferred props](#deferred-props)\n  * [Merging props](#merging-props)\n  * [History encryption](#history-encryption)\n  * [Server-side rendering](#server-side-rendering)\n  * [Vite helper](#vite-helper)\n    - [Examples](#examples-1)\n\n## Demo\n\nDemo is available at https://inertianetcore-d5c7hcggg7afdqg0.germanywestcentral-01.azurewebsites.net/\n\nIf you want to see how it exactly works, you can clone this repository and play with [InertiaNetCore.Demo](InertiaNetCore.Demo). It contains a simple Vue.js frontend and an ASP.NET Core backend.\n\n## Installation\n\n1. Using Package Manager:\n```shell\nInstall-Package InertiaNetCore\n```\n\n2. Using .NET CLI:\n```shell\ndotnet add package InertiaNetCore\n```\n\n3. Using NuGet Package Manager: search for `InertiaNetCore`\n\n## Getting started\n\n### 1. Enabling the library\n\nYou need to add few lines to the `Program.cs` or `Starup.cs` file.\n\n```csharp\nusing InertiaNetCore.Extensions;\n\n[...]\n\nbuilder.Services.AddInertia();\nbuilder.Services.AddViteHelper(); // assuming you are using Vite\n\n[...]\n\napp.UseInertia();\n\n```\n\nGo to the [Configuration](#configuration) section to see all available options.\n\n### 2. Creating the root view for the app\n\nCreate the file `/Views/App.cshtml` with the following content:\n\n```html\n@using InertiaNetCore\n@model InertiaPage\n\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\"/\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/\u003e\n    \u003ctitle inertia\u003eMy App\u003c/title\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n@await Inertia.Html(Model)\n\n@Vite.Input(\"src/app.ts\")\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\u003e [!NOTE]\n\u003e Default root view is `App.cshtml` but you can change it by setting `RootView` in `AddInertia` method in `Program.cs`.\n\n### 3. Passing data to the frontend\n\nTo pass data to a page component, use `Inertia.Render()`.\n\n```csharp\n[Route(\"about\")]\npublic IActionResult About()\n{\n    return Inertia.Render(\"pages/PageAbout\", new InertiaProps\n    {\n        [\"Name\"] = \"InertiaNetCore\",\n        [\"Version\"] = Assembly.GetAssembly(typeof(Inertia))?.GetName().Version?.ToString()\n    });\n}\n```\n\n\u003e [!NOTE]\n\u003e To make a form endpoint, remember to add `[FromBody]` to your model parameter, because the request data is passed using\nJSON.\n\n```csharp\n[HttpPost]\npublic async Task\u003cIActionResult\u003e Create([FromBody] Post post)\n{\n    if (!ModelState.IsValid)\n    {\n        // The validation errors are passed automatically.\n        return await Index();\n    }\n    \n    _context.Add(post);\n    await _context.SaveChangesAsync();\n    \n    return RedirectToAction(\"Index\");\n}\n```\n\n\n## Configuration\n\nBoth `AddInertia` and `AddViteHelper` methods have optional parameters to configure the library.\n\nFor example, you can change JSON serializer settings to use `Newtonsoft.Json` instead of `System.Text.Json`.\n\n```csharp\nbuilder.Services.AddInertia(options =\u003e\n{\n    var options = new JsonSerializerSettings\n    {\n        ContractResolver = new CamelCasePropertyNamesContractResolver(),\n        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,\n    };\n    o.Json = InertiaJsonOptions.Create(options); // there is also an optional parameter to customize the \"Serialize\" method\n});\n```\n\nVisit the [InertiaOptions](InertiaNetCore/Models/InertiaOptions.cs) and [ViteOptions](InertiaNetCore/Models/ViteOptions.cs) classes to see all available options.\n\n\n## Features\n\n### Shared data\n\nYou can add some shared data to your views using for example middlewares:\n\n```csharp\nusing InertiaNetCore;\nusing InertiaNetCore.Extensions;\nusing InertiaNetCore.Models;\n\n[...]\n\napp.Use(async (context, next) =\u003e\n{\n    Inertia.Share( new InertiaProps\n    {\n        [\"Auth\"] = new InertiaProps\n        {\n            [\"Token\"] = \"123456789\",\n            [\"Username\"] = \"Mergehez\",\n        }\n    });\n            \n    await next();\n});\n\n// you can also use AddInertiaSharedData extension method to do the same thing\napp.AddInertiaSharedData(httpContext =\u003e new InertiaProps\n{\n    [\"Auth\"] = new InertiaProps\n    {\n        [\"Token\"] = \"123456789\",\n        [\"Username\"] = \"Mergehez\",\n    }\n});\n```\n\n### Flash Messages\n\nYou can add flash messages to your responses using the `Inertia.Flash(...)` or `Inertia.Back(url).WithFlash(...)` methods.\n    \n```csharp\n[HttpDelete(\"{id:int}\")]\npublic async Task\u003cIActionResult\u003e Destroy(int id)\n{\n    // find user\n    \n    // delete user\n    \n    Inertia.Flash(\"success\", \"User deleted.\"); // set it anywhere in the app\n    return Redirect(\"/users\");\n    \n    // or one-liner in case you use Inertia.Back()\n    return Inertia.Back().WithFlash(\"success\", \"User deleted.\");\n}\n```\n\n### Deferred props\n\nDeferred props allow you to defer the loading of certain page data until after the initial page render. (see [Inertia.js docs](https://v2.inertiajs.com/deferred-props))\n\nIn the example below, the `Posts` prop will be loaded after the initial page render.\n\n```csharp\npublic IActionResult Profile()\n{\n    return Inertia.Render(\"pages/Profile\", new InertiaProps\n    {\n        [\"Foo\"] = \"Bar\", \n        [\"Posts\"] = Inertia.Defer(async () =\u003e\n        {\n            return await _context.Posts.ToListAsync();\n        })\n    });\n}\n```\n\n\u003e [!NOTE]\n\u003e Deferred props are supported starting from Inertia.js v2.0\n\n\n### Merging props\n\nBy default, Inertia overwrites props with the same name when reloading a page. However, there are instances, such as pagination or infinite scrolling, where that is not the desired behavior. In these cases, you can merge props instead of overwriting them. (see [Inertia.js docs](https://v2.inertiajs.com/merging-props))\n\n```csharp\npublic IActionResult Users(int page, int perPage)\n{\n    return Inertia.Render(\"pages/Users\", new InertiaProps\n    {\n        [\"Results\"] = Inertia.Merge(async () =\u003e\n        {\n            return await GetPaginatedUsers(page, perPage);\n        })\n    });\n}\n```\n\n\u003e [!NOTE]\n\u003e Merging props are supported starting from Inertia.js v2.0\n\n### History encryption\n\nSee [Inertia.js docs](https://v2.inertiajs.com/history-encryption) for more information.\n\nHistory encryption is an opt-in feature. There are several methods for enabling it:\n\n#### Global encryption:\n\nIf you'd like to enable history encryption globally, set the `EncryptHistory` option to `true` in `AddInertia` method in `Program.cs`.\n\n```csharp\nbuilder.Services.AddInertia(options =\u003e\n{\n    options.EncryptHistory = true;\n});\n```\n\n#### Per-request encryption:\n   To encrypt the history of an individual request, simply call the `Inertia.EncryptHistory()` method before returning the response.\n\n```csharp\nInertia.EncryptHistory();\n```\n\n#### Clearing encrypted history:\nTo clear the history state, you can call the `Inertia.ClearHistory()` method before returning the response.\n\n```csharp\nInertia.ClearHistory();\n```\n\n\u003e [!NOTE]\n\u003e History encryption is supported starting from Inertia.js v2.0\n\n### Server-side rendering\n\nIf you want to enable SSR in your Inertia app, remember to add `Inertia.Head()` to your layout:\n\n```diff\n@using InertiaNetCore\n@model InertiaNetCore.InertiaPage\n\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\"/\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/\u003e\n    \u003ctitle inertia\u003eMy App\u003c/title\u003e\n\n+   @await Inertia.Head(Model)\n\u003c/head\u003e\n\n\u003cbody\u003e\n@await Inertia.Html(Model)\n\n@Vite.Input(\"src/app.ts\")\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nand enable the SSR option in `Program.cs`.\n\n```csharp\nbuilder.Services.AddInertia(options =\u003e\n{\n    options.SsrEnabled = true;\n    \n    // You can optionally set a different URL than the default.\n    options.SsrUrl = \"http://127.0.0.1:13714/render\"; // default\n});\n```\n\n### Vite Helper\n\nA 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.\n\nTo get started with the Vite Helper, you have to use the `AddViteHelper` extension method in `Program.cs`.\n\n```csharp\nusing InertiaNetCore.Extensions;\n\n[...]\n\nbuilder.Services.AddViteHelper();\n\n// Or with options (default values shown)\n\nbuilder.Services.AddViteHelper(options =\u003e\n{\n    options.PublicDirectory = \"wwwroot\";\n    options.BuildDirectory = \"build\";\n    options.HotFile = \"hot\";\n    options.ManifestFilename = \"manifest.json\";\n});\n```\n\n#### Examples\n\nHere's an example for a TypeScript Vue app with Hot Reload:\n\n```html\n@using InertiaNetCore\n\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\"/\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/\u003e\n    \u003ctitle inertia\u003eMy App\u003c/title\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n@await Inertia.Html(Model)\n\n@Vite.Input(\"src/app.ts\")\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nAnd here is the corresponding `vite.config.js`\n\n```js\nimport vue from '@vitejs/plugin-vue';\nimport { defineConfig } from 'vite';\nimport path from 'path';\nimport laravel from 'laravel-vite-plugin';\nimport { mkdirSync } from 'node:fs';\n\nconst outDir = '../../wwwroot/build';\nmkdirSync(outDir, { recursive: true });\n\nexport default defineConfig({\n    plugins: [\n        laravel({\n            input: ['src/app.ts', 'src/app.scss'],\n            publicDirectory: outDir,\n            refresh: true,\n        }),\n        vue({\n            template: {\n                transformAssetUrls: {\n                    base: null,\n                    includeAbsolute: false,\n                },\n            },\n        }),\n    ],\n    resolve: {\n        alias: {\n            '@': path.resolve(__dirname, 'src'),\n        },\n    },\n    build: {\n        outDir,\n        emptyOutDir: true,\n    },\n});\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmergehez%2Finertianetcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmergehez%2Finertianetcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmergehez%2Finertianetcore/lists"}