Contribute to Docs Contribute to Docs

Middleware

The first components in the ASP.NET pipeline are Middleware. Middleware can either handle a request completely, or process the incoming request and pass it on to the next component in the pipeline.

As Piranha CMS is built around standard ASP.NET components most of its middleware is used for routing and passes the request on to eventually be handled by the web application.

Registering The Middleware

The middleware components are added when calling UseCms in ConfigureServices. The following code sets up middleware for all available content.

Standard Setup

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApi api)
{
    ...

    // Configure Piranha
    app.UsePiranha(options => 
    {
        options.UseCms();

        ...
    });
    
    ...
}

This call is equivalent to setting up the entire web application and adding the following middleware components (in the specified order). Please note that the routing middleware handles all of the existing content types.

  1. Routing Middleware
  2. Sitemap Middleware

Middleware Routing

The routing middleware will perform the following operations on the request in the specified order.

1. Resolve Site

The middleware first tries to resolve the current site by looking at the hostname and the first url-segment, for example:

mysite.com/en

If a match can't be found it continues by resolving the site using only the hostname. If the current hostname can't be found it will use the default site of the application.

You can bypass this entire step by disabling UseSiteRouting in your startup in which case the default site will always be used.

app.UsePiranha(options => 
{
    options.UseCms(o =>
    {
        o.UseSiteRouting = false;
    });
});

2. Resolve Alias

GET mysite.com/alias

After the site has been resolved the middleware tries to find an alias that matches the requested url. If such an alias is found the middleware will return a temporary or permanent redirect depending on the alias.

You can bypass this entire step by disabling UseAliasRouting in your startup.

app.UsePiranha(options => 
{
    options.UseCms(o =>
    {
        o.UseAliasRouting = false;
    });
});

3. Resolve Page

GET mysite.com/pageSlug

After this the middleware will try to resolve the page deepest in the hierarchical sitemap that matches the requested url. If a page is found it is stored for later processing.

As this step is needed for several other actions you can't bypass it entirely, but you can disable the request for being rewritten for pages by disabling UsePageRouting and/or UseStartpageRouting in your startup.

app.UsePiranha(options => 
{
    options.UseCms(o =>
    {
        o.UsePageRouting = false;
        o.UseStartpageRouting = false;
    });
});

4. Resolve Post

GET mysite.com/pageSlug/postSlug

If a page was found in the previous step and that page is an archive the middleware will, using the next segment in the requested url, try to resolve a post from that archive.

You can bypass this entire step by disabling UsePostRouting in your startup.

app.UsePiranha(options => 
{
    options.UseCms(o =>
    {
        o.UsePostRouting = false;
    });
});

5. Rewrite Request

For more detailed information about how routing for content types works, please refer to Routing and Advanced Routing.

After the previous operations have been performed the middleware rewrites the request to the ASP.NET application using the following rules.

5.1 Rewrite Post Request

If a post was found the request is rewritten to the route of the post. Possible query string and remaining url segments are passed along to that route.

5.2 Rewrite Page Request

If a page was found that wasn't an archive the request is rewritten to the route of the page. Possible query string and remaining url segments are passed along to that route.

5.3 Rewrite Archive Request

If a page was found that was an archive the middleware inspects the remaining segments in the requested url to resolve parameters for the archive.

Standard Request

GET /<pageSlug>/<year?>/<month?>(/page/<pageNum>)?

Filtered By Category

GET /<pageSlug>/category/<categorySlug>/<year?>/<month?>(/page/<pageNum>)?

Filtered By Tag

GET /<pageSlug>/tag/<tagSlug>/<year?>/<month?>(/page/<pageNum>)?

Possible Filters

All parameters are optional except pageSlug, but the optional paging must be placed last. Everything after the page number is ignored. This means that the following URL's would be valid:

  • /myblog
  • /myblog/category/fishing
  • /myblog/tag/salmon
  • /myblog/page/2
  • /myblog/category/fishing/page/2
  • /myblog/tag/salmon/page/2
  • /myblog/2018
  • /myblog/category/fishing/2018
  • /myblog/tag/salmon/2018
  • /myblog/2018/page/2
  • /myblog/category/fishing/2018/page/2
  • /myblog/tag/salmon/2018/page/2
  • /myblog/2018/1
  • /myblog/category/fishing/2018/1
  • /myblog/tag/salmon/2018/1
  • /myblog/2018/1/page/2
  • /myblog/category/fishing/2018/1/page/2
  • /myblog/tag/salmon/2018/1/page/2