{"id":13596165,"url":"https://github.com/DamianEdwards/RazorSlices","last_synced_at":"2025-04-09T16:31:42.720Z","repository":{"id":125584952,"uuid":"610557440","full_name":"DamianEdwards/RazorSlices","owner":"DamianEdwards","description":"Lightweight Razor-based templates for ASP.NET Core without MVC, Razor Pages, or Blazor.","archived":false,"fork":false,"pushed_at":"2024-12-21T01:07:04.000Z","size":26217,"stargazers_count":401,"open_issues_count":20,"forks_count":19,"subscribers_count":21,"default_branch":"main","last_synced_at":"2025-04-05T00:49:47.661Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","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/DamianEdwards.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":"2023-03-07T02:20:48.000Z","updated_at":"2025-04-03T14:04:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"133a100f-ffe2-454f-a729-7259aec35d96","html_url":"https://github.com/DamianEdwards/RazorSlices","commit_stats":{"total_commits":61,"total_committers":3,"mean_commits":"20.333333333333332","dds":"0.032786885245901676","last_synced_commit":"4b65ac38e2f6ab9292a42e3eac31489e262f0c0a"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DamianEdwards%2FRazorSlices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DamianEdwards%2FRazorSlices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DamianEdwards%2FRazorSlices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DamianEdwards%2FRazorSlices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DamianEdwards","download_url":"https://codeload.github.com/DamianEdwards/RazorSlices/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247419824,"owners_count":20936012,"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":[],"created_at":"2024-08-01T16:02:10.689Z","updated_at":"2025-04-09T16:31:37.710Z","avatar_url":"https://github.com/DamianEdwards.png","language":"HTML","readme":"# Razor Slices\n\n[![CI (main)](https://github.com/DamianEdwards/RazorSlices/actions/workflows/ci.yml/badge.svg)](https://github.com/DamianEdwards/RazorSlices/actions/workflows/ci.yml)\n[![Nuget](https://img.shields.io/nuget/v/RazorSlices)](https://www.nuget.org/packages/RazorSlices/)\n\n*Lightweight* Razor-based templates for ASP.NET Core without MVC, Razor Pages, or Blazor, optimized for high-performance, unbuffered rendering with low allocations. Compatible with trimming and native AOT. Great for returning dynamically rendered HTML from Minimal APIs, middleware, etc. Supports .NET 8+\n\n- [Getting Started](#getting-started)\n- [Installation](#installation)\n- [Features](#features)\n\n## Getting Started\n\n1. [Install the NuGet package](#installation) into your ASP.NET Core project (.NET 8+):\n\n    ``` shell\n    \u003e dotnet add package RazorSlices\n    ```\n\n1. Create a directory in your project called *Slices* and add a *_ViewImports.cshtml* file to it with the following content:\n\n    ``` cshtml\n    @inherits RazorSliceHttpResult\n\n    @using System.Globalization;\n    @using Microsoft.AspNetCore.Razor;\n    @using Microsoft.AspNetCore.Http.HttpResults;\n    \n    @tagHelperPrefix __disable_tagHelpers__:\n    @removeTagHelper *, Microsoft.AspNetCore.Mvc.Razor\n    ```\n\n1. In the same directory, add a *Hello.cshtml* file with the following content:\n\n    ``` cshtml\n    @inherits RazorSliceHttpResult\u003cDateTime\u003e\n    \u003c!DOCTYPE html\u003e\n    \u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eHello from Razor Slices!\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cp\u003e\n            Hello from Razor Slices! The time is @Model\n        \u003c/p\u003e\n    \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n\n    Each *.cshtml* file will have a proxy type generated for it by the Razor Slices source generator that you can use as the generic argument to the various APIs in Razor Slices for rendering slices.\n\n1. Add a minimal API to return the slice in your *Program.cs*:\n\n    ``` c#\n    app.MapGet(\"/hello\", () =\u003e Results.Extensions.RazorSlice\u003cMyApp.Slices.Hello, DateTime\u003e(DateTime.Now));\n    ```\n\n## Installation\n\n### NuGet Releases\n\n[![Nuget](https://img.shields.io/nuget/v/RazorSlices)](https://www.nuget.org/packages/RazorSlices/)\n\nThis package is currently available from [nuget.org](https://www.nuget.org/packages/RazorSlices/):\n\n``` console\n\u003e dotnet add package RazorSlices\n```\n\n### CI Builds\n\nIf you wish to use builds from this repo's `main` branch you can install them from [this repo's package feed](https://github.com/DamianEdwards/RazorSlices/pkgs/nuget/RazorSlices).\n\n1. [Create a personal access token](https://github.com/settings/tokens/new) for your GitHub account with the `read:packages` scope with your desired expiration length:\n\n    [\u003cimg width=\"583\" alt=\"image\" src=\"https://user-images.githubusercontent.com/249088/160220117-7e79822e-a18a-445c-89ff-b3d9ca84892f.png\"\u003e](https://github.com/settings/tokens/new)\n\n1. At the command line, navigate to your user profile directory and run the following command to add the package feed to your NuGet configuration, replacing the `\u003cGITHUB_USER_NAME\u003e` and `\u003cPERSONAL_ACCESS_TOKEN\u003e` placeholders with the relevant values:\n\n    ``` shell\n    ~\u003e dotnet nuget add source -n GitHub -u \u003cGITHUB_USER_NAME\u003e -p \u003cPERSONAL_ACCESS_TOKEN\u003e https://nuget.pkg.github.com/DamianEdwards/index.json\n    ```\n\n1. You should now be able to add a reference to the package specifying a version from the [repository packages feed](https://github.com/DamianEdwards/RazorSlices/pkgs/nuget/RazorSlices)\n\n1. See [these instructions](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry) for further details about working with GitHub package feeds.\n\n## Features\n\nThe library is still new and features are being actively added.\n\n### Currently supported\n\n- ASP.NET Core 8.0 and above\n- Strongly-typed models (via `@inherits RazorSlice\u003cMyModel\u003e` or `@inherits RazorSliceHttpResult\u003cMyModel\u003e`)\n- Razor constructs:\n  - [Implicit expressions](https://learn.microsoft.com/aspnet/core/mvc/views/razor#implicit-razor-expressions), e.g. `@someVariable`\n  - [Explicit expressions](https://learn.microsoft.com/aspnet/core/mvc/views/razor#implicit-razor-expressions), e.g. `@(someBool ? thisThing : thatThing)`\n  - [Control structures](https://learn.microsoft.com/aspnet/core/mvc/views/razor#control-structures), e.g. `@if()`, `@switch()`, etc.\n  - [Looping](https://learn.microsoft.com/aspnet/core/mvc/views/razor#looping-for-foreach-while-and-do-while), e.g. `@for`, `@foreach`, `@while`, `@do`\n  - [Code blocks](https://learn.microsoft.com/aspnet/core/mvc/views/razor#razor-code-blocks), e.g. `@{ var someThing = someOtherThing; }`\n  - [Conditional attribute rendering](https://learn.microsoft.com/aspnet/core/mvc/views/razor#conditional-attribute-rendering)\n  - Functions, e.g.\n\n    ```cshtml\n    @functions {\n        private readonly string _someString = \"A very important string\";\n        private int DoAThing() =\u003e 123;\n    }\n    ```\n  \n  - [Templated Razor delegates](https://learn.microsoft.com/aspnet/core/mvc/views/razor#templated-razor-delegates), e.g.\n\n    ```cshtml\n    @inherits RazorSlice\u003cTodo\u003e\n\n    \u003ch1\u003e@Title(Model)\u003c/h1\u003e\n\n    @functions {\n        private IHtmlContent Title(Todo todo)\n        {\n            \u003ctext\u003eTodo @todo.Id: @todo.Title\u003c/text\u003e\n            return HtmlString.Empty;\n        }\n    }\n    ```\n\n- DI-activated properties via `@inject`\n- Rendering slices from slices (aka partials) via `@(await RenderPartialAsync\u003cMyPartial\u003e())`\n- Using slices as layouts for other slices, including layouts with strongly-typed models:\n  - For the layout slice, inherit from `RazorLayoutSlice` or `RazorLayoutSlice\u003cTModel\u003e` and use `@await RenderBodyAsync()` in the layout to render the body\n\n      ```cshtml\n      @inherits RazorLayoutSlice\u003cLayoutModel\u003e\n\n      \u003c!DOCTYPE html\u003e\n      \u003chtml lang=\"en\"\u003e\n      \u003chead\u003e\n          \u003ctitle\u003e@Model.Title\u003c/title\u003e\n          @await RenderSectionAsync(\"head\")\n      \u003c/head\u003e\n      \u003cbody\u003e\n        @await RenderBodyAsync()\n\n        \u003cfooter\u003e\n            @await RenderSectionAsync(\"footer\")\n        \u003c/footer\u003e\n      \u003c/body\u003e\n      \u003c/html\u003e\n      ```\n\n  - For the slice using the layout, implement `IUsesLayout\u003cTLayout\u003e` or `IUsesLayout\u003cTLayout, TModel\u003e` to declare which layout to use. If using a layout with a model, ensure you implement the `LayoutModel` property in your `@functions` block, e.g\n\n      ```cshtml\n      @inherits RazorSlice\u003cSomeModel\u003e\n      @implements IUsesLayout\u003cLayoutSlice, LayoutModel\u003e\n\n      \u003cdiv\u003e\n          @* Content here *@\n      \u003c/div\u003e\n\n      @functions {\n          public LayoutModel LayoutModel =\u003e new() { Title = \"My Layout\" };\n      }\n      ```\n\n  - Layouts can render sections via `@await RenderSectionAsync(\"SectionName\")` and slices can render content into sections by overriding `ExecuteSectionAsync`, e.g.:\n\n      ```cshtml\n      protected override Task ExecuteSectionAsync(string name)\n      {\n          if (name == \"lorem-header\")\n          {\n              \u003cp class=\"text-info\"\u003eThis page renders a custom \u003ccode\u003eIHtmlContent\u003c/code\u003e type that contains lorem ipsum content.\u003c/p\u003e\n          }\n\n          return Task.CompletedTask;\n      }\n      ```\n\n    **Note: The `@section` directive is not supported as it's incompatible with the rendering approach of Razor Slices**\n\n- Asynchronous rendering, i.e. the template can contain `await` statements, e.g. `@await WriteTheThing()`\n- Writing UTF8 `byte[]` values directly to the output\n- Rendering directly to `PipeWriter`, `Stream`, `TextWriter`, `StringBuilder`, and `string` outputs, including optimizations for not boxing struct values, zero-allocation rendering of primitives like numbers, etc. (rather than just calling `ToString()` on everything)\n- Return a slice instance directly as an `IResult` in minimal APIs via `@inherits RazorSliceHttpResult` and `Results.Extensions.RazorSlice(\"/Slices/Hello.cshtml\")`\n- Full support for trimming and native AOT when used in conjunction with ASP.NET Core Minimal APIs\n\n### Interested in supporting but not sure yet\n\n- Extensions to help support using HTMX with Razor Slices \n- Getting small updates to the Razor compiler itself to get some usability and performance improvements, e.g.:\n  - Don't mark the template's `ExecuteAsync` method as an `async` method unless the template contains `await` statements to save on the async state machine overhead\n  - Support compiling static template elements to UTF8 string literals (`ReadOnlySpan\u003cbyte\u003e`) instead of string literals to save on the UTF16 to UTF8 conversion during rendering\n  - Support disabling the default registered `@addtaghelper` and `@model` directives which rely on MVC\n\n### No intention to support\n\n- Tag Helpers and View Components (they're tied to MVC and are intrinsically \"heavy\")\n- `@model` directive (the Razor compiler does not support its use in conjunction with custom base-types via `@inherits`)\n- `@attribute [Authorize]` (wrong layer of abstraction for minimal APIs, etc.)\n- `@section` directive (the Razor compiler emits code that is incompatible with the rendering approach of Razor Slices)\n","funding_links":[],"categories":["others","HTML","Content"],"sub_categories":["164. [RazorSlices](https://ignatandrei.github.io/RSCG_Examples/v2/docs/RazorSlices) , in the [Templating](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#templating) category"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDamianEdwards%2FRazorSlices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDamianEdwards%2FRazorSlices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDamianEdwards%2FRazorSlices/lists"}