### Example SignIn Implementation Source: https://piranhacms.org/docs/master/extensions/authentication An example implementation of the SignIn method for a custom security provider, handling HTTP context and claims. ```csharp public async Task SignIn(object context, string username, string password) { if (context is HttpContext) { if (Authenticate(username, password)) { var user = Users .Single(u => u.UserName == username && u.Password == password); var claims = new List(); foreach (var claim in user.Claims) { claims.Add(new Claim(claim, claim)); } claims.Add(new Claim(ClaimTypes.Name, user.UserName)); claims.Add(new Claim(ClaimTypes.Sid, user.Id)); var identity = new ClaimsIdentity(claims, user.Password); var principle = new ClaimsPrincipal(identity); await ((HttpContext)context) .SignInAsync("Piranha.SimpleSecurity", principle); return true; } return false; } throw new ArgumentException("SimpleSecurity only works with a HttpContext"); } ``` -------------------------------- ### Example Module Implementation Source: https://piranhacms.org/docs/master/extensions An example implementation of the `IModule` interface, registering a custom block type during module initialization. ```csharp using Piranha; using Piranha.Extend; namespace SimpleModule { /// /// The identity module. /// public class Module : IModule { /// /// Gets the Author /// public string Author => "Test Author"; /// /// Gets the Name /// public string Name => "SimpleModule"; /// /// Gets the Version /// public string Version => Piranha.Utils .GetAssemblyVersion(GetType().Assembly); /// /// Gets the description /// public string Description => "Simple Module"; /// /// Gets the package url. /// public string PackageUrl => "https://www.nuget.org/packages/SimpleModule"; /// /// Gets the icon url. /// public string IconUrl => "http://piranhacms.org/assets/twitter-shield.png"; /// /// Initializes the module. /// public void Init() { App.Blocks.Register(); } } } ``` -------------------------------- ### Install Frontend Dependencies Source: https://piranhacms.org/docs/master/basics/project-templates Installs frontend dependencies for projects using SCSS styles, typically required if not using Visual Studio. Run this command in the project's root directory. ```bash > npm install ``` -------------------------------- ### SimpleModule Implementation Example Source: https://piranhacms.org/docs/master/extensions/modules An example implementation of the `IModule` interface, registering a custom block type. ```csharp using Piranha; using Piranha.Extend; namespace SimpleModule { /// /// The identity module. /// public class Module : IModule { /// /// Gets the Author /// public string Author => "Test Author"; /// /// Gets the Name /// public string Name => "SimpleModule"; /// /// Gets the Version /// public string Version => Piranha.Utils .GetAssemblyVersion(GetType().Assembly); /// /// Gets the description /// public string Description => "Simple Module"; /// /// Gets the package url. /// public string PackageUrl => "https://www.nuget.org/packages/SimpleModule"; /// /// Gets the icon url. /// public string IconUrl => "http://piranhacms.org/assets/twitter-shield.png"; /// /// Initializes the module. /// public void Init() { App.Blocks.Register(); } } } ``` -------------------------------- ### Install Piranha CMS Project Templates Source: https://piranhacms.org/docs/master/basics/prerequisites Use this command to install all available Piranha CMS project templates. This simplifies starting new projects with pre-configured structures. ```bash dotnet new -i Piranha.Templates ``` -------------------------------- ### Install Piranha CMS Templates Source: https://piranhacms.org/docs/master/basics/project-templates Installs the Piranha CMS project templates using the .NET CLI. Use this command to get started with creating new Piranha CMS projects. ```bash > dotnet new -i Piranha.Templates ``` -------------------------------- ### Accessing Site Helper Source: https://piranhacms.org/docs/master/application/services/application-service Get the site helper via WebApp.Site to retrieve information about the current site. ```cshtml @WebApp.Site ``` -------------------------------- ### ConfigureServices with Piranha Setup (Classic Startup) Source: https://piranhacms.org/docs/master/basics/application-setup Register Piranha CMS services and configure options like CMS, Manager UI, File Storage, ImageSharp, Caching, TinyMCE, EF Core, and Identity. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddPiranha(options => { options.UseCms(); options.UseManager(); options.UseFileStorage(naming: Piranha.Local.FileStorageNaming.UniqueFolderNames); options.UseImageSharp(); options.UseMemoryCache(); options.UseTinyMCE(); options.UseEF(db => db.UseSqlite("Filename=./PiranhaWeb.db")); options.UseIdentityWithSeed(db => db.UseSqlite("Filename=./PiranhaWeb.db")); }); } ``` -------------------------------- ### Add Custom Authorization Policies in Startup.cs Source: https://piranhacms.org/docs/master/tutorials/securing-pages Define custom authorization policies in the ConfigureServices method of Startup.cs to manage access to secured content. This example adds a 'ReadSecuredPosts' policy. ```csharp public void ConfigureServices(IServiceCollection services) { ... // Add custom policies services.AddAuthorization(o => { // Read secured posts o.AddPolicy("ReadSecuredPosts", policy => { policy.RequireClaim("ReadSecuredPosts", "ReadSecuredPosts"); }); }); } ``` -------------------------------- ### Get Site Prefix Source: https://piranhacms.org/docs/master/application/helpers/site-helper Retrieves the optional site prefix if the current site is routed with a host and prefix. ```cshtml @WebApp.Site.SitePrefix ``` -------------------------------- ### Media Item Object Structure Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/media-picker This is an example of the media object structure that will be passed to the callback function when a media item is selected. ```javascript { contentType: "image/png", filename: "banner.png", folderId: "96cf512e-9f10-4488-95cc-e92204769fb5", ​ height: 861, id: "ac34a625-b140-445b-b948-3221a0b02292", lastModified: "2019-10-17", publicUrl: "https://...", size: "674,73 KB", type: "Image", width: 1310 } ``` -------------------------------- ### Get Site Description Fields Source: https://piranhacms.org/docs/master/application/helpers/site-helper Retrieves standard description fields for the site, including title, body, and logo. ```cshtml @WebApp.Site.Description.Title @WebApp.Site.Description.Body @WebApp.Site.Description.Logo ``` -------------------------------- ### Registering Application Service Source: https://piranhacms.org/docs/master/application/services/application-service The Application Service is automatically registered when `UseCms()` is called in `ConfigureServices` during Piranha CMS setup. ```csharp services.AddPiranha(options => { options.UseCms(); ... }); ``` -------------------------------- ### Get Site Culture Source: https://piranhacms.org/docs/master/application/helpers/site-helper Retrieves the culture information for the language selected for the current site. ```cshtml @WebApp.Site.Culture ``` -------------------------------- ### Implement Audio Field Source: https://piranhacms.org/docs/master/content/fields Uses the `AudioField` to reference media assets from the audio library. It supports implicit conversions to and from `Guid` and `Media`. ```csharp using Piranha.AttributeBuilder; using Piranha.Models; using Piranha.Extend.Fields; public MyPage : Page { public class ComplexRegion { [Field] public AudioField MyAudio { get; set; } ... } [Region] public ComplexRegion MyRegion { get; set; } } ``` -------------------------------- ### Get Request Scheme Source: https://piranhacms.org/docs/master/application/helpers/request-helper Retrieves the current scheme (e.g., http, https) from the HTTP request. ```csharp @WebApp.Request.Scheme ``` -------------------------------- ### Accessing Media Helper Source: https://piranhacms.org/docs/master/application/services/application-service Get the media helper instance via WebApp.Media to manipulate uploaded media. Requires an Image Manipulation service to be registered. ```cshtml @WebApp.Media ``` -------------------------------- ### Add Piranha CMS Web Packages Source: https://piranhacms.org/docs/master/basics/project-setup Install the Piranha.AspNetCore package to enable middleware components for routing and request handling in integrated websites. ```xml ``` -------------------------------- ### Page Picker Callback Object Structure Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/page-picker This is an example of the page object structure that will be passed to the callback function when a page is selected. ```json { "id": "a16eb9ee-1c3f-4b04-b223-5a8f2b655f63", "siteId": "f376a89d-230e-4eee-8b02-78b8ff83e693", "title": "About us", "typeName": "Content Page", "published": "2019-10-17", "status": "", "editUrl": "manager/page/edit/", "isCopy": false, "isDraft": false, "isExpanded": true, "permalink": "/about-us", "items":[] } ``` -------------------------------- ### SimpleStringField Implementation Source: https://piranhacms.org/docs/master/content/fields/custom-fields Example implementation of a custom string field. It implements the IField interface and uses the FieldTypeAttribute to define its name and component. ```csharp using Piranha; using Piranha.Extend; [FieldType(Name = "Simple String", Component = "simple-field")] public class SimpleStringField : IField { public string Value { get; set; } public string GetTitle() { return Value; } public void Init() { // Nothing special for this field } } ``` -------------------------------- ### Retrieve and Display Draft Content Source: https://piranhacms.org/docs/master/application/previewing Use the 'draft' query parameter to fetch and display draft content. If no draft exists, it falls back to the live version. This example shows how to retrieve an archive page draft. ```csharp [Route("/page")] public async Task GetPage(Guid id, int? year = null, int? month = null, int? page = null, Guid? category = null, Guid? tag = null, bool draft = false) { SimpleArchivePage pageModel = null; if(draft) { pageModel = await _api.Pages.GetDraftByIdAsync(id); } // if the draft is true but this is null that means there were no changes // and we are simply previewing the live version if(pageModel == null) { pageModel = await _api.Pages.GetByIdAsync(id); } pageModel.Archive = await _api.Archives.GetByIdAsync(id); return View(pageModel); } ``` -------------------------------- ### Accessing Request Helper Source: https://piranhacms.org/docs/master/application/services/application-service Obtain the request helper via WebApp.Request to get information about the current HTTP request. ```cshtml @WebApp.Request ``` -------------------------------- ### Implementing a Generic Author Block Source: https://piranhacms.org/docs/master/content/blocks/custom-blocks Example of a generic custom block 'AuthorBlock' that omits the 'Component' property, allowing Piranha to handle rendering. ```csharp using Piranha.Extend; using Piranha.Extend.Fields; [BlockType(Name = "Author", Category = "Content", Icon = "fas fa-use")] public class AuthorBlock : Block { public StringField Name { get; set; } public ImageField Image { get; set; } public HtmlField Description { get; set; } } ``` -------------------------------- ### Get Content Async Source: https://piranhacms.org/docs/master/application/helpers/site-helper Asynchronously retrieves the current site content with a specified Site Type. Use this for Site Global Content registered and selected for your site. ```csharp var content = await WebApp.Site.GetContentAsync(); ``` -------------------------------- ### Register Piranha CMS Middleware Source: https://piranhacms.org/docs/master/application/middleware Standard setup for Piranha CMS middleware within the ASP.NET Core `Configure` method. ```csharp public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApi api) { ... // Configure Piranha app.UsePiranha(options => { options.UseCms(); ... }); ... } ``` -------------------------------- ### Disable Startpage Routing Source: https://piranhacms.org/docs/master/basics/startup-options Configures whether start page routing should be enabled in the middleware pipeline. Defaults to true. ```csharp services.AddPiranha(options => { options.UseCms(o => { o.UseStartpageRouting = false; }); }); ``` -------------------------------- ### Configure EF Core with SQLite Source: https://piranhacms.org/docs/master/basics/database-setup Configure Piranha CMS to use Entity Framework Core with an SQLite database in the `ConfigureServices` method of `Startup.cs`. This example uses `SQLiteDb` as the context. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddPiranha(options => { ... options.UseEF(db => db.UseSqlite("Filename=./PiranhaWeb.db")); }); } ``` -------------------------------- ### Get Site Content by Type Source: https://piranhacms.org/docs/master/application Retrieves the current site content with a specified Site Type. Used for Site Global Content when a Type is registered and selected for the site. ```cshtml @{ var content = await WebApp.Site.GetContentAsync(); } ``` -------------------------------- ### Resize Image Block in Template Source: https://piranhacms.org/docs/master/content/blocks Example of how to resize an image block within a web template using the Media.ResizeImage helper. The width parameter specifies the maximum width. ```cshtml @model Piranha.Extend.Blocks.ImageBlock ``` -------------------------------- ### Configure .NET 6 Application Startup Source: https://piranhacms.org/docs/master/basics/application-setup Use WebApplicationBuilder to add Piranha services and configure CMS, manager, storage, image processing, editor, caching, and identity options. Then build the WebApplication and configure middleware. ```csharp var builder = WebApplication.CreateBuilder(args); builder.AddPiranha(options => { options.UseCms(); options.UseManager(); options.UseFileStorage(naming: Piranha.Local.FileStorageNaming.UniqueFolderNames); options.UseImageSharp(); options.UseTinyMCE(); options.UseMemoryCache(); options.UseEF(db => db.UseSqlite("Filename=./PiranhaWeb.db")); options.UseIdentityWithSeed(db => db.UseSqlite("Filename=./PiranhaWeb.db")); }); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UsePiranha(options => { App.Init(options.Api); options.UseManager(); options.UseTinyMCE(); options.UseIdentity(); }); app.Run(); ``` -------------------------------- ### Getting Site Content by Type Source: https://piranhacms.org/docs/master/application/services/application-service Fetch the current site's content of a specific type using WebApp.Site.GetContentAsync(). Used for site global content when a specific Site Type is registered. ```cshtml @{ var content = await WebApp.Site.GetContentAsync(); } ``` -------------------------------- ### Configure with Piranha Initialization and Middleware (Classic Startup) Source: https://piranhacms.org/docs/master/basics/application-setup Initialize the Piranha application with the IApi and configure middleware for the Manager UI, TinyMCE, and Identity. ```csharp public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApi api) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } App.Init(api); app.UsePiranha(options => { options.UseManager(); options.UseTinyMCE(); options.UseIdentity(); }); } ``` -------------------------------- ### Configure EF Core with SQLite and Connection Pool Size Source: https://piranhacms.org/docs/master/basics/database-setup Configure Piranha CMS to use Entity Framework Core with an SQLite database and specify a custom connection pool size. This example sets the `poolSize` to 32. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddPiranha(options => { ... options.UseEF(db => db.UseSqlite("Filename=./PiranhaWeb.db"), poolSize: 32); }); } ``` -------------------------------- ### Classic ASP.NET Core Startup Template Source: https://piranhacms.org/docs/master/basics/application-setup Default startup methods for an empty ASP.NET Core web application. ```csharp public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); }); }); } ``` -------------------------------- ### VideoField in Complex Region Source: https://piranhacms.org/docs/master/content/fields The VideoField has a Guid reference to the assigned media asset id and implicit operators for converting it from and to a Guid and a Media asset. The media library is filtered to only show folders and videos. ```csharp using Piranha.AttributeBuilder; using Piranha.Models; using Piranha.Extend.Fields; public MyPage : Page { public class ComplexRegion { [Field] public VideoField MyVideoValue { get; set; } ... } [Region] public ComplexRegion MyRegion { get; set; } } ``` -------------------------------- ### Site Properties Source: https://piranhacms.org/docs/master/application/helpers/site-helper Access properties to get information about the current site. ```APIDOC ## Site Properties ### Description Provides access to various properties of the current site. ### Properties - **Id**: Gets the `id` for the current site. - **LanguageId**: Gets the `LanguageId` for the current site. - **Culture**: Gets the `Culture` for the language selected for the current site. - **SitePrefix**: Gets the optional site prefix of the current site if it is routed with `host/prefix`. - **Description**: Gets the standard description fields available for the site (Title, Body, Logo). - **Sitemap**: Gets the `Sitemap` for the current site. This can for example be used for rendering menus. The result only contains the currently **published** nodes, but hidden nodes are included and must be handled by the application. ``` -------------------------------- ### Using Application Service Helpers Source: https://piranhacms.org/docs/master/application/services Illustrates how to use the helper objects provided by the Application Service for Media, Request, and Site operations. ```APIDOC ## Using Application Service Helpers ### Description Leverage the helper objects within the Application Service to interact with media, request details, and site information. ### Helpers - **Media**: Gets the media helper which provides methods for manipulating media. - **Request**: Gets the request helper which provides information about the current request. - **Site**: Gets the site helper which provides information about the site currently being requested. ### Usage Example ```csharp @WebApp.Media @WebApp.Request @WebApp.Site ``` ``` -------------------------------- ### Get Site ID Source: https://piranhacms.org/docs/master/application/helpers/site-helper Retrieves the unique identifier for the current site. ```cshtml @WebApp.Site.Id ``` -------------------------------- ### Create New ASP.NET Project Source: https://piranhacms.org/docs/master/basics/project-setup Use this command to create a new empty ASP.NET Core web application from the terminal. ```bash dotnet new web ``` -------------------------------- ### Get Request Host Source: https://piranhacms.org/docs/master/application/helpers/request-helper Retrieves the current hostname from the HTTP request. ```csharp @WebApp.Request.Host ``` -------------------------------- ### Get Site Language ID Source: https://piranhacms.org/docs/master/application/helpers/site-helper Retrieves the language identifier for the current site. ```cshtml @WebApp.Site.LanguageId ``` -------------------------------- ### Get Request Port Source: https://piranhacms.org/docs/master/application/helpers/request-helper Retrieves the current port number from the HTTP request. ```csharp @WebApp.Request.Port ``` -------------------------------- ### .NET 6 ASP.NET Core Startup Template Source: https://piranhacms.org/docs/master/basics/application-setup Default startup methods for an empty ASP.NET Core web application using .NET 6+ minimal APIs. ```csharp var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run(); ``` -------------------------------- ### Open Media Picker with Inline Callback Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/media-picker Demonstrates how to open the media picker using an inline callback function to handle the selected media object. ```javascript piranha.mediapicker.open(function (m) { console.log(m); }); ``` -------------------------------- ### Get Raw Request URL Source: https://piranhacms.org/docs/master/application/helpers/request-helper Retrieves the raw requested URL before any middleware rewriting. ```csharp @WebApp.Request.Url ``` -------------------------------- ### Configure Routing via appsettings.json Source: https://piranhacms.org/docs/master/basics/startup-options Demonstrates configuring Piranha routing options in `appsettings.json` and binding them in `Startup.cs`. ```json { "Piranha": { "Routing": { "UseSiteRouting": false } } } ``` ```csharp public Startup(IConfiguration configuration) { _config = configuration; } public void ConfigureServices(IServiceCollection services) { services.AddPiranha(options => { options.UseCms(o => _config.GetSection("Piranha") ?.GetSection("Routing") ?.Bind(o)); }); } ``` -------------------------------- ### Specify Database Provider Source: https://piranhacms.org/docs/master/basics/project-templates When creating a new project, you can specify the database provider using the `-d` or `--database` option. Supported providers include SQLite, SQLServer, MySql, and PostgreSql. Defaults to SQLite. ```bash -d|--database Specifies the database provider that should be used SQLite - Use SQLite as database SQLServer - Use SQL Server as database MySql - Use MySql as database PostgreSql - Use PostgreSql as database Default: SQLite ``` -------------------------------- ### Init Method Signatures Source: https://piranhacms.org/docs/master/content/fields/custom-fields The Init method initializes the field for client use, loading additional resources. It supports Dependency Injection for accessing registered services. ```csharp // Synchronous Init method void Init(...); // Asyncronous Init method Task Init(...); ``` -------------------------------- ### Implementing a Quote Block Source: https://piranhacms.org/docs/master/content/blocks/custom-blocks Example of a custom block class 'QuoteBlock' inheriting from Piranha.Extend.Block, marked with the BlockType attribute. ```csharp using Piranha.Extend; using Piranha.Extend.Fields; [BlockType(Name = "Quote", Category = "Content", Icon = "fas fa-quote-right", Component = "quote-block")] public class QuoteBlock : Block { /// /// Gets/sets the text body. /// public TextField Body { get; set; } } ``` -------------------------------- ### Get Posts for a Specific Archive Source: https://piranhacms.org/docs/master/tutorials/access-archives-and-posts Retrieves all posts belonging to a single specified archive page. Specify the archivePageId. ```csharp var archivePosts = api.Posts.GetAll(archivePageId); ``` -------------------------------- ### Implement 401 Unauthorized Redirect Middleware Source: https://piranhacms.org/docs/master/tutorials/securing-pages Add a custom middleware in Startup.cs's Configure method to intercept 401 Unauthorized responses and redirect users to a specified login page. This handles unauthorized access to secured pages. ```csharp public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApi api) { ... // Custom middleware that checks for status 401 app.Use(async (ctx, next) => { await next(); if (ctx.Response.StatusCode == 401) { ctx.Response.Redirect("/login"); } }); // Standard Piranha middleware app.UsePiranha(options => { options.UseManager(); options.UseTinyMCE(); options.UseIdentity(); }); } ``` -------------------------------- ### Configure Media CDN URL Source: https://piranhacms.org/docs/master/basics/configuration Sets the base URL for the media CDN. An empty string means no CDN is configured. ```csharp config.MediaCDN = ""; ``` -------------------------------- ### Open Media Preview Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/media-preview Call the open method with the media.id to preview uploaded media. ```javascript piranha.preview.open(mediaId); ``` -------------------------------- ### Getting Current Post Object Source: https://piranhacms.org/docs/master/application/services/application-service Access the current post object if the HTTP request is for a post via WebApp.CurrentPost. ```cshtml @WebApp.CurrentPost ``` -------------------------------- ### Import All Site Types from Assembly Source: https://piranhacms.org/docs/master/content/sites Imports all content types defined within a specified assembly. This simplifies startup configuration when adding new types. ```csharp using Piranha.AttributeBuilder; var builder = new ContentTypeBuilder(api) .AddAssembly(typeof(Startup).Assembly); builder.Build(); ``` -------------------------------- ### Getting Current Page Object Source: https://piranhacms.org/docs/master/application/services/application-service Access the current page object if the HTTP request is for a page via WebApp.CurrentPage. ```cshtml @WebApp.CurrentPage ``` -------------------------------- ### Register and Use Simple Module Extensions Source: https://piranhacms.org/docs/master/extensions Extension methods for registering a module with Piranha CMS and configuring its static file serving. Ensure these are called in Startup.cs. ```csharp using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Piranha; using SimpleModule; public static class SimpleModuleExtensions { public static IServiceCollection AddSimpleModule(this IServiceCollection services) { App.Modules.Register(); return services; } public static IApplicationBuilder UseSimpleModule(this IApplicationBuilder builder) { // Manager resources App.Modules.Manager().Scripts .Add("~/manager/simplemodule/js/header-block.js"); // Add the embedded resources return builder.UseStaticFiles(new StaticFileOptions { FileProvider = new EmbeddedFileProvider(typeof(SimpleModuleExtensions).Assembly, "SimpleModule.assets.dist"), RequestPath = "/manager/simplemodule" }); } } ``` ```csharp public void ConfigureServices(IServiceCollection services) { ... services.AddSimpleModule(); ... } public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApi api) { ... app.UseSimpleModule(); ... } ``` -------------------------------- ### Inject Piranha.Config in Startup Source: https://piranhacms.org/docs/master/basics/configuration Inject `Piranha.Config` into your `Configure` method to access and modify configuration settings. ```csharp public void Configure(..., Piranha.Config config) { ... } ``` -------------------------------- ### Add Post Link Block Source: https://piranhacms.org/docs/master/content/blocks Demonstrates how to add a PostBlock to a page, referencing an existing post. Ensure the post exists and is accessible. ```csharp using Piranha.Extend.Blocks; var page = await MyPage.CreateAsync(api); var reference = await api.Posts.GetBySlugAsync("blog", "my-blogpost"); page.Blocks.Add(new PostBlock { Body = reference }); ``` -------------------------------- ### Query All Media Assets in Root Folder Source: https://piranhacms.org/docs/master/content/media Retrieve all media assets from the root folder of the media library using the IApi interface. ```csharp using System.Collections.Generic; using System.Threading.Tasks; using Piranha; using Piranha.Media; public Task> GetMediaInRootFolder(IApi api) { return api.Media.GetAllAsync(); } ``` -------------------------------- ### Synchronous and Asynchronous Block Initialization Source: https://piranhacms.org/docs/master/content/blocks/custom-blocks These methods are used to initialize blocks for client or manager use, supporting dependency injection for custom data loading. ```csharp // Synchronous Init method void Init(...); // Asyncronous Init method Task Init(...); ``` ```csharp // Synchronous Init method void InitManager(...); // Asyncronous Init method Task InitManager(...); ``` -------------------------------- ### Registering a Custom Field Source: https://piranhacms.org/docs/master/content/fields/custom-fields Custom fields must be registered with Piranha.App.Fields after the application has been initialized. This example shows how to register the SimpleStringField. ```csharp Piranha.App.Init(api); // Register custom fields Piranha.App.Fields.Register(); ``` -------------------------------- ### Get Current Page ID Source: https://piranhacms.org/docs/master/application Retrieves the ID of the currently requested page. Useful for rendering menus or sitemap-based structures. ```cshtml @WebApp.PageId ``` -------------------------------- ### Open Media Picker Method Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/media-picker Use this method to open the media picker. It accepts a callback function that is executed when a media item is selected. Optional filter and folderId parameters can be provided. ```javascript piranha.mediapicker.open(callback, filter = null, folderId = null); ``` -------------------------------- ### Set Media Description Source: https://piranhacms.org/docs/master/content/media Add a descriptive text to a media asset for more context. ```csharp media.Description = "This is an image of me backpacking."; ``` -------------------------------- ### Open Media Preview Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/media-preview Opens a modal to preview a media item. The preview is displayed if the media type is supported. The modal also provides options to view media details and update the media by uploading a new file. ```APIDOC ## Open Media Preview ### Description Opens a modal to preview a media item using its ID. ### Method `piranha.preview.open(mediaId)` ### Parameters #### Path Parameters - **mediaId** (number) - Required - The ID of the media item to preview. ``` -------------------------------- ### Add an Info Class Archive Property Source: https://piranhacms.org/docs/master/content/archives Use `PostArchive` for archives where regions or blocks are not needed. These models are cached for performance. ```csharp [PageType(Title = "Simple Archive", UseBlocks = false, IsArchive = true)] public class SimpleArchive : Page { public PostArchive Archive { get; set; } } var model = await api.Pages.GetByIdAsync(id); model.Archive = await api.Archives.GetByIdAsync(...); ``` -------------------------------- ### Limit Allowed Block Types Source: https://piranhacms.org/docs/master/content/posts Restricts the available block types for a post type using `BlockItemTypeAttribute`. This example allows only `HtmlBlock`. ```csharp [PageType(Title = "Special Post")] [BlockItemType(typeof(Piranha.Extend.Blocks.HtmlBlock))] public class SpecialPost : Page { ... } ``` -------------------------------- ### Open Page Picker with Inline Callback Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/page-picker Demonstrates how to open the page picker and handle the selection using an inline anonymous function as the callback. ```javascript piranha.pagepicker.open(function (page) { console.log(page); }); ``` -------------------------------- ### Get All Posts from All Archives Source: https://piranhacms.org/docs/master/tutorials/access-archives-and-posts Retrieves all posts of type PostBase from all archive pages. Use PostInfo for posts without regions and blocks. ```csharp var allPosts = api.Posts.GetAll(); ``` ```csharp var smallPosts = api.Posts.GetAll(); ``` ```csharp var somePosts = api.Posts.GetAll(); ``` -------------------------------- ### Get Site Sitemap Source: https://piranhacms.org/docs/master/application Retrieves the sitemap for the current site. Includes published nodes and hidden nodes which must be handled by the application. ```cshtml @{ var sitemap = WebApp.Site.Sitemap; } ``` -------------------------------- ### Get Current Post Object Source: https://piranhacms.org/docs/master/application Retrieves the currently requested post object if the HTTP request is for a post. Returns null otherwise. ```cshtml @WebApp.CurrentPost ``` -------------------------------- ### Registering Custom Authentication Service Source: https://piranhacms.org/docs/master/extensions/authentication Shows how to register a custom ISecurity implementation in the application's service collection. ```csharp services.AddSingleton(); ``` -------------------------------- ### Getting Current Page ID Source: https://piranhacms.org/docs/master/application/services/application-service Retrieve the ID of the currently requested page using the WebApp.PageId property. Useful for sitemap-based rendering. ```cshtml @WebApp.PageId ``` -------------------------------- ### Add Host Entries to Windows Hosts File Source: https://piranhacms.org/docs/master/tutorials/how-to-use-multitenancy Add these lines to your Windows hosts file to map custom domain names to your local machine for testing multitenant websites. ```text 127.0.0.1 www.piranhatest1.com 127.0.0.1 www.piranhatest2.com ``` -------------------------------- ### Get Current Page Object Source: https://piranhacms.org/docs/master/application Retrieves the currently requested page object if the HTTP request is for a page. Returns null otherwise. ```cshtml @WebApp.CurrentPage ``` -------------------------------- ### Checking for Nullable Number Field Value in Razor Source: https://piranhacms.org/docs/master/content/fields Provides an example of how to safely check and display the value of a nullable NumberField in a Razor view. ```cshtml @model MyPage @if (Model.MyRegion.MyNumberValue.Value.HasValue) {

The number is @Model.MyRegion.MyNumberValue.Value

} ``` -------------------------------- ### piranha.mediapicker.open Source: https://piranhacms.org/docs/master/manager-architecture/vue-components/media-picker Opens the media picker interface to allow users to select a media item. A callback function is executed upon selection. ```APIDOC ## piranha.mediapicker.open(callback, filter = null, folderId = null) ### Description Opens the media picker and returns the selected media item via a callback function. ### Parameters #### callback - **Function** - Required - The function to be called when a media item is selected. It accepts one parameter: the selected media object. #### filter - **String** - Optional - Used to filter media assets. Valid values: `Audio`, `Document`, `Image`, `Video`. #### folderId - **String** - Optional - The ID of the folder to open in the media picker. ### Request Example ```javascript piranha.mediapicker.open(function (m) { console.log(m); }); ``` ### Response Example (Media Object) ```json { "contentType": "image/png", "filename": "banner.png", "folderId": "96cf512e-9f10-4488-95cc-e92204769fb5", "height": 861, "id": "ac34a625-b140-445b-b948-3221a0b02292", "lastModified": "2019-10-17", "publicUrl": "https://...", "size": "674,73 KB", "type": "Image", "width": 1310 } ``` ``` -------------------------------- ### Import a Single Post Type Source: https://piranhacms.org/docs/master/content/posts Imports a specific post type into Piranha CMS during application startup. Ensure the `Piranha.AttributeBuilder` package is installed. ```csharp using Piranha.AttributeBuilder; var builder = new ContentTypeBuilder(api) .AddType(typeof(SimplePost)); builder.Build(); ``` -------------------------------- ### Register Custom Block and Resources in Startup.cs Source: https://piranhacms.org/docs/master/tutorials/add-custom-block Registers the custom RawHtmlBlock with Piranha CMS and includes the custom JavaScript and CSS files in the manager interface. These lines should be added after App.Init(). ```csharp public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApi api) { ... App.Blocks.Register(); App.Modules.Manager().Scripts.Add("~/custom-blocks.js"); App.Modules.Manager().Styles.Add("~/custom-blocks.css"); ... } ``` -------------------------------- ### Access Media Helper Source: https://piranhacms.org/docs/master/application Provides access to the media helper for manipulating uploaded media. Requires an Image Manipulation service to be registered. ```cshtml @WebApp.Media ``` -------------------------------- ### Get Site Sitemap Source: https://piranhacms.org/docs/master/application/helpers/site-helper Retrieves the sitemap for the current site, used for rendering menus. Includes hidden nodes which must be handled by the application. ```csharp var sitemap = WebApp.Site.Sitemap; ``` -------------------------------- ### ImageFieldSerializer Implementation Source: https://piranhacms.org/docs/master/extensions/serializers An example serializer for ImageField that stores only the image's ID. It serializes the Id to a string and deserializes the string back into an ImageField object. ```csharp using Piranha.Extend; using Piranha.Extend.Fields; public class ImageFieldSerializer : ISerializer { public string Serialize(object obj) { if (obj is ImageField) { return ((ImageField)obj).Id.ToString(); } throw new ArgumentException(); } public object Deserialize(string str) { return new ImageField { Id = !string.IsNullOrEmpty(str) ? new Guid(str) : (Guid?)null }; } } ``` -------------------------------- ### Custom Login Page Model Source: https://piranhacms.org/docs/master/tutorials/securing-pages Implement a custom login page model for handling user authentication. This model uses the ISecurity service to sign in users. ```csharp using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Piranha; namespace AuthTest.Pages { public class LoginPageModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel { private readonly ISecurity _security; [BindProperty] public string Username { get; set; } [BindProperty] public string Password { get; set; } public LoginPageModel(ISecurity security) : base() { _security = security; } public async Task OnPostAsync() { if (ModelState.IsValid && await _security.SignIn(HttpContext, Username, Password)) return new RedirectResult("/"); return Page(); } } } ``` -------------------------------- ### Get Categories and Tags for an Archive Source: https://piranhacms.org/docs/master/tutorials/access-archives-and-posts Asynchronously retrieves all categories and tags associated with a specific archive page. Requires the Archive Page's Id. ```csharp var categories = await api.GetAllCategoriesAsync(WebApp.CurrentPage.Id); var tags = await api.GetAllTagsAsync(WebApp.CurrentPage.Id); ``` -------------------------------- ### Getting Site Sitemap Source: https://piranhacms.org/docs/master/application/services/application-service Retrieve the sitemap for the current site using WebApp.Site.Sitemap. This includes published nodes and hidden nodes that need application-level handling. ```cshtml @{ var sitemap = WebApp.Site.Sitemap; } ``` -------------------------------- ### Configure HTML Excerpt Source: https://piranhacms.org/docs/master/basics/configuration Determines if Page & Post excerpts should be rendered as HTML or plain text. Defaults to false. ```csharp config.HtmlExcerpt = false; ``` -------------------------------- ### Define a Custom Block Group Source: https://piranhacms.org/docs/master/content/blocks/custom-block-groups Inherit from Piranha.Extend.BlockGroup and use attributes to configure its type, category, and icon. This example defines an ImageGalleryBlock that accepts ImageBlock items. ```csharp using Piranha.Extend; using Piranha.Extend.Fields; [BlockGroupType(Name = "Gallery", Category = "Media", Icon = "fas fa-images")] [BlockItemType(Type = typeof(ImageBlock))] public class ImageGalleryBlock : BlockGroup { } ``` -------------------------------- ### Accessing Application Service Properties Source: https://piranhacms.org/docs/master/application/services Demonstrates how to access key properties of the Application Service, such as the API instance, current page ID, current page object, and current post object. ```APIDOC ## Accessing Application Service Properties ### Description Access the core components of the Piranha CMS application service for the current request. ### Properties - **Api**: Gives you access to the current scoped `IApi` instance. - **PageId**: Gets the id of the currently requested page. This is useful when rendering menus or other structures based on the sitemap. - **CurrentPage**: Gets the currently requested page **if** the current HTTP request is for a page. - **CurrentPost**: Gets the currently requested post **if** the current HTTP request is for a post. ### Usage Example ```csharp @WebApp.Api @WebApp.PageId @WebApp.CurrentPage @WebApp.CurrentPost ``` ``` -------------------------------- ### ResizeImage (Media) Source: https://piranhacms.org/docs/master/application/helpers/media-helper Resizes the given Media object to the specified dimensions and returns the PublicUrl to the resized file. If only width is specified, the image is scaled with the same proportions. If both width and height are specified, the image is scaled and cropped. ```APIDOC ## ResizeImage (Media) ### Description Resizes the given `Media` to the specified dimensions and returns the `PublicUrl` to the resized file. If only width is specified the image is **scaled** with the same proportions. If both width and height is specified the image is both **scaled and cropped**. ### Method Signature `@WebApp.Media.ResizeImage(Media image, int width, int? height = null)` ``` -------------------------------- ### Add Video Block Source: https://piranhacms.org/docs/master/content/blocks Demonstrates adding a VideoBlock by referencing a video media asset. This block only supports videos uploaded as Piranha media assets. ```csharp using Piranha.Extend.Blocks; using Piranha.Models; var page = await MyPage.CreateAsync(api); var video = api.Media.GetAll().First(m => m.Type == MediaType.Video); page.Blocks.Add(new VideoBlock { Body = video }); ``` -------------------------------- ### Add Audio Block to Page Source: https://piranhacms.org/docs/master/content/blocks Demonstrates how to add an AudioBlock to a page using the Piranha API. Ensure you have an audio media item available. ```csharp using Piranha.Extend.Blocks; using Piranha.Models; var page = await MyPage.CreateAsync(api); var audio = api.Media.GetAll().First(m => m.Type == MediaType.Audio); page.Blocks.Add(new AudioBlock { Body = audio }); ``` -------------------------------- ### Integrate Footer into Layout (_Layout.cshtml) Source: https://piranhacms.org/docs/master/tutorials/how-to-create-a-footer This HTML snippet demonstrates how to render the footer content within your website's layout file (_Layout.cshtml). It retrieves the current site's 'DemoSite' content and displays the logo and text from the footer region. ```html
@{ var currentSite = await WebApp.Site.GetContentAsync(); } @if (currentSite != null) {
@Html.Raw(currentSite.FooterContents.Logo)
@Html.Raw(currentSite.FooterContents.Text)
}
``` -------------------------------- ### Configure Archive Page Size Source: https://piranhacms.org/docs/master/basics/configuration Sets the number of posts to display in an archive. A value of 0 returns all available posts. ```csharp config.ArchivePageSize = 0; ``` -------------------------------- ### Create Piranha MVC Project Source: https://piranhacms.org/docs/master/basics/project-templates Creates a new Piranha CMS project configured for ASP.NET MVC. This template includes default Content Types and Views, and offers to seed test data on first run. ```bash > dotnet new piranha.mvc ``` -------------------------------- ### MediaHelper.ResizeImage Source: https://piranhacms.org/docs/master/application/services Provides methods to resize images using either an ImageField or Media object, returning the public URL to the resized file. ```APIDOC ## MediaHelper.ResizeImage ### Description Resizes the given image to the specified dimensions and returns the `PublicUrl` to the resized file. If only width is specified the image is **scaled** with the same proportions. If both width and height are specified the image is both **scaled and cropped**. ### Methods - **ResizeImage(ImageField image, int width, int? height = null)**: Resizes an `ImageField`. - **ResizeImage(Media image, int width, int? height = null)**: Resizes a `Media` object. ### Usage Example ```csharp @WebApp.Media.ResizeImage(Image image, int width, int? height = null) @WebApp.Media.ResizeImage(Media image, int width, int? height = null) ``` ``` -------------------------------- ### Access Site Helper Source: https://piranhacms.org/docs/master/application Provides access to the site helper for information about the currently requested site. ```cshtml @WebApp.Site ``` -------------------------------- ### Add a Base Class Archive Property Source: https://piranhacms.org/docs/master/content/archives For archives supporting multiple post types, use `PostArchive` and check the type of each post during rendering. This allows for flexibility but requires type checking. ```csharp [PageType(Title = "Simple Archive", UseBlocks = false, IsArchive = true)] public class SimpleArchive : Page { public PostArchive Archive { get; set; } } var model = await api.Pages.GetByIdAsync(id); model.Archive = await api.Archives.GetByIdAsync(...); foreach (var post in model.Archive) { if (post is BlogPost) { ... } else if (post is NewsPost) { ... } } ``` -------------------------------- ### Configure Project File for Piranha CMS Source: https://piranhacms.org/docs/master/basics/project-setup Add an ItemGroup to your .csproj file to include Piranha CMS core packages. This is required before adding specific package references. ```xml net6.0 ``` -------------------------------- ### Rendering Raw HTML in Razor View Source: https://piranhacms.org/docs/master/content/fields Illustrates how to render markdown content as raw HTML in a Razor view to preserve formatting. ```cshtml @model MyPage

@Model.Title

@Html.Raw(Model.MyMarkdownValue) ``` -------------------------------- ### Import a Single Site Type Source: https://piranhacms.org/docs/master/content/sites Imports a specific site type into the Piranha CMS application during startup. Ensure the `api` object is available. ```csharp using Piranha.AttributeBuilder; var builder = new ContentTypeBuilder(api) .AddType(typeof(SimpleSite)); builder.Build(); ``` -------------------------------- ### Create Razor Pages Project Source: https://piranhacms.org/docs/master/basics/project-templates Use this command to create a new Piranha CMS project with Razor Pages. The application can optionally seed test data on first run. ```bash > dotnet new piranha.razor ``` -------------------------------- ### Configure Page Type as Archive Source: https://piranhacms.org/docs/master/content/pages Sets a Page Type to be used as an Archive Page. The default value for `IsArchive` is false. ```csharp [PageType(IsArchive = true)] ``` -------------------------------- ### Manager Init Method Signatures Source: https://piranhacms.org/docs/master/content/fields/custom-fields The InitManager method initializes the field when loaded within the manager interface. It also supports Dependency Injection for accessing services. ```csharp // Synchronous Init method void InitManager(...); // Asyncronous Init method Task InitManager(...); ```