| « Orchard Indexing | Half Orchard » |
Rewrite Module
Recently, after the release of the first public version of Orchard, I have created a bunch of modules as external contributions, even though I am in the core team. And actually the whole team has released some contributed modules.
So far, I have released 12 modules on the gallery, some of them being co-authored with other team members. But the issue is that apart from a link to the source code and a simple name, you don’t have any hint on what it is supposed to do. There is a documentation page though on www.codeplex.com</a> for each of them, but I am lazy, so I figured it could be easier to provide at least a blog post to explain the overall goals and usage for those modules.
Origins
Let’s talk a little bit about the Rewrite Module. As for most of the modules I have created, it started on an existing problem that needed a solution. In this case we were about to launch the Orchard Contest website (www.orchardproject.net/omc</a>), and we had a SSL certificate for the www.orchardproject.net domain. The SSL was working great and it was a breeze to configure IIS in order to use it. But Bradley, a PM on Orchard responsible for this site, discovered that when users were coming using the orchardproject.net domain, without the www subdomain, then the HTTPS security alert was shown in browsers. Normal as the certificate was for a single domain. Too late to order another one, or even better a wildcard one as going through the Verisign process would have been too long for us. So I suggested Bradley we could hack a specific MVC Filter in this application to automatically redirect users to the correct domain, but one idea coming after the other, I ended up creating a more complete module … typically me!
The Orchard Contest website is built on Orchard itself. Thus we could leverage the users management, a theme that Jon, a web/UX designer in our team, had already created, and also have another case study for Orchard. So instead of creating a simple hard coded MVC filter, let’s create a reusable Orchard module. What could have be reused was the simple one rule redirect stuff. And it reminded me how it is done in PHP applications running on Apache with .htaccess files. IIS has simple and yet very powerful tools to handle url rewriting, and it can even parse Apache .htaccess files, but the goal of a CMS is also to have a single configuration point for the whole application, so having a module makes sense as you might not have access to IIS manager when using a shared hosting provider.
And that’s it! The Rewrite Module is a .htaccess file handler, which enables a lot of possibilities in you Orchard hosting story. Once installed and enabled, a new settings section is created and looks like this:
How to use it
You might have noticed the little text under the rule editing zone, linking to the current Apache documentation. Why bother creating some documentation that already exists! Another link that I like a lot is http://corz.org/serv/tricks/htaccess2.php, because it provides a lot of interesting scenarios that can be done with this module, like:
- preventing hot linking
- blocking specific IP ranges
- blocking specific browser agents or crawlers
- forcing SSL
- domain redirections
- …
For instance, in the Orchard Contest website we use this rule to redirect users to the correct domain:
RewriteCond %{HTTP_HOST} ^orchardproject.net$ [NC]
RewriteRule ^(.*)$ http://www.orchardproject.net/$1 [R=301,NC,L]
Implementation details
The implementation is quite simple. First there is a RedirectSettingsPart and the associated record class to store the settings.
public class RedirectSettingsPart : ContentPart<RedirectSettingsPartRecord> {
public string Rules {
get { return Record.Rules; }
set { Record.Rules = value; }
}
public bool Enabled {
get { return Record.Enabled; }
set { Record.Enabled = value; }
}
}
Like other settings parts, there is also a driver, handler, migration and template file. But that’s a common and well documented implementation.
The most important part is to handle all requests and trigger specific actions based on the rules in these settings. This is done by implementing IActionFilter which lets us being called whenever a controller’s action is executed. In Orchard we also need to inherit from FilterProvider in order to getting registered.
public class RedirectFilter : FilterProvider, IActionFilter {
private readonly IOrchardServices _services;
public RedirectFilter(IOrchardServices services) {
_services = services;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void OnActionExecuted(ActionExecutedContext filterContext) { }
public void OnActionExecuting(ActionExecutingContext filterContext) {
// implementation
}
}
This event can then return specific ActionResult objects. So after parsing the rewirte rules, and checked a condition is fulfilled, there are actually three different possible results:
- HttpUnauthorizedResult
- RedirectResult, when a permanent redirect is requested
- TransferResult, for non permanents redirects, preventing for having the user to send another request
TransferResult is a simple custom ActionResult implementation:
/// <summary>
/// Transfers execution to the supplied url.
/// </summary>
private class TransferResult : RedirectResult {
public TransferResult(string url)
: base(url) {}
public override void ExecuteResult(ControllerContext context) {
var httpContext = HttpContext.Current;
httpContext.RewritePath(Url, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
}
}
I hope this little story will encourage you into creating reusable modules instead of doing one shot code. And if you happen to use this module someday, let me know.
As for most modules you can find on the gallery, there is a codeplex project for it, http://orchardrewriterules.codeplex.com, where you can submit bugs, get the source code, or read some documentation … when there will be some.
Trackback address for this post
Feedback awaiting moderation
This post has 70 feedbacks awaiting moderation...