Sometime's you'll want to implement pages that take custom parameters and then performs some business logic, but are still positioned within the sitemap like a regular content page. Luckily this is not a problem at all since Piranha only rewrites the part of the requested URL that can be matched to a permalink and leaves the rest for your application to handle.
Let's for example say we wanted to implement a page in our site that shows details about a product, but the product data is in fact in another system.
We're going to start by creating a new Page Type
that has it's own unique Route
configured to handle our product details. We're also going to disable blocks as we don't want a lot of extra content taking up space.
using Piranha.AttributeBuilder;
using Piranha.Models;
[PageType(Title = "Product Page", UseBlocks = false)]
[ContentTypeRoute(Title = "Default", Route = "/productpage")]
public class ProductPage : Page<ProductPage>
{
public MyProduct SelectedProduct { get; set; }
...
}
This page type could of course contain any number of Regions
, Fields
or Blocks
you want it to have.
Next up we need to create an Action
that handles our new route. This action can be added to any controller you want as long as the route matches the one specified on the Page Type.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Piranha;
public class MyController : Controller
{
private readonly IApi _api;
private readonly IProductApi _productApi;
public MyController(IApi api, IProductApi productApi)
{
_api = api;
_productApi = productApi;
}
[Route("/productpage/{productId?}")]
public async Task<IActionResult> ProductPage(Guid id, string productId = null)
{
if (!string.IsNullOrEmpty(productId))
{
// Get the page from Piranha
var model = await _api.Pages.GetByIdAsync<ProductPage>(id);
// Get the selected product from our external system
model.SelectedProduct = _productApi.GetProductById(productId);
return View(model);
}
else
{
// TODO: Someone came here without a product id, handle it gracefully.
}
}
}
Since the routing of Piranha doesn't know that we want a product id the page will be matched even when no product id is requested. For this reason this should always be handled. Another way to handle it is to create an Alias
for the permalink of the page (with no product id) that performs a redirect to another page.
Now let's say we publish our product detail page in our site on the permalink /products/details
and we have some kind landing page for our products at /products
, we can now request it by calling.
GET /products/details/the-first-product
GET /products/details/the-second-product
Both of these requests will end up on the same page in Piranha with the additional route parameter available in the actions in productId
.