Tales from the Evil Empire

Bertrand Le Roy's blog


Bertrand Le Roy

BoudinFatal's Gamercard

Tales from the Evil Empire - Blogged

Blogs I read

My other stuff


February 2013 - Posts

Always have a host or URL prefix on the default Orchard tenant

The multi-tenancy feature in Orchard enables you to host multiple sites within the same Orchard instance. It’s not a a security feature, just a way to improve site density, and to enable you to save on hosting costs. Nevertheless, a request to a specific existing tenant should never be answered with a page from another tenant. Ever.

There is however a fallback mechanism that enables one tenant to handle all requests that weren’t identified by another tenant. While this could be considered useful in some scenarios, I’m hereby declaring it bad practice.

If for any reason a tenant fails to start, for example, requests to that tenant are going to fall back. Even if you were in a scenario where you considered fallback to be useful, this is an unexpected and positively undesirable result. It’s much better to fail with an error message or a 404 than to fail with a fallback to a different site than the one the client asked for.

So here is my recommendation:

Always have a host or URL prefix configured on all tenants, in particular the default tenant.

This way, no fallback will ever happen, and requests will only be handled by a tenant that recognizes its own host name.

Here is, for example, the new configuration of the default tenant on my hosted web sites:

Always specify the host name on your Orchard tenants

Note that I have multiple hosts configured here, including the host that I use on my dev machine for local development, but the point here is to specify something on all tenants.

This is important.

Easy content templates for Orchard, take 2

Placement.info is an XML file that orchestrates the different parts of a content item and sends each of the shapes they create into specific local content zones. If the previous sentence sounded confusing to you, fear not, this post is for you.

When writing an Orchard theme, more often than not, you know exactly what parts exist in your content type, and you know where you want them to render. Placement can be extremely powerful, but it’s rather abstract and it reverses the usual logic of placing contents on a page. What most people really want to do is write a template with simple markup and placeholders inside that markup for the rendering of specific parts such as title, summary, tags, etc. Placement forces you to dispatch those part shapes from a completely separate file.

In the Summer of 2011, I wrote a little article to explain how to write custom templates for specific content types in Orchard, without using placement.info:

So you don’t want to use placement.info?

The solution worked, but relied on a hack that will break with the next version of Orchard (1.7).

Sébastien Ros gave me a little trick the other day that enables the same thing, in a simpler, less hacky form. It still uses placement somewhat, but in a very simple way.

The idea is to create one local zone per part instead of the usual header, content and footer zones. Here we are going to send the relevant shapes to those zones through placement:

<Match ContentType="BlogPost">
  <Match DisplayType="Summary">
    <Place Parts_Common_Body_Summary="Summary:0"
           Parts_Comments_Count="CommentsCount:0" />

This sends shapes into Summary, Tags, MetadataSummary and CommentsCount zones. Those do not yet exist.

Caveat: when naming your custom zones, be careful not to collide with existing properties or zones on the Model, lest you end up with unexpected and confusing results. Using longish and very explicit names usually works well for that.

The template can now simply create and render those zones. Here is my Content-BlogPost.Summary.cshtml template:

@using Orchard.ContentManagement
    var blogPost = Model.ContentItem;
<article class="content-item blog-post">
    <header><h1><a href="@Url.ItemDisplayUrl((IContent)blogPost)">
</a></h1></header> @Display(Model.Summary) <footer> @Display(Model.Tags) @Display(Model.MetadataSummary) @Display(Model.CommentsCount) </footer> </article>

Notice how in the case of the title, I’m not even using the shape given by the part, but I’m accessing the properties directly on the TitlePart. The other parts are rendered through the special zone that we created using the Display function. And that is all. You can now focus on building your template, and it will be pretty obvious what will render where…

Creating simple custom Orchard widgets

If you want to create a simple widget in Orchard, such as a box of social links, you have three possibilities:

  1. Find a module on the gallery or write one yourself, but there is overhead associated with modules, which may make this overkill.
  2. Use an HTML widget and paste a bunch of HTML and Javascript, hoping administrators of the site don’t break it accidentally. I don’t like this, it feels like a hack.
  3. Create a simple widget, following the instructions in this post.

First, let’s create a content type (in the admin, go to Content / Content Types and click “Create new type”) and call it “Social Links”.

Add the widget and identity parts. Those are the only ones you really need:

Pick the identity and widget parts

Uncheck creatable and draftable, add the “Widget” stereotype (with an upper-case ‘W’: I made the mistake, as you can see, of using a lower-case ‘w’ on my first try, and it did prevent the widget from being seen as such):

configuring the new type

Now when you add a widget, the social links widget appears in the list:

The new widget can now be added to a zone

It’s a simple, apparently featureless widget, which minimizes the chances of accidentally messing it up.

All that’s left to do now is to add a template to the theme that will render what we want. We’ll take advantage of shape alternates. Using shape tracing, we quickly discover that we can name our template Widget-SocialLinks.cshtml to target it narrowly enough:

Shape tracing can show us how to override the rendering

Once the file has been added to the Views folder of my theme, I can paste in the code from Facebook, Twitter, or whatever else I want in there.

All done

Done. Fastest and simplest way to create a new widget.

More Posts