Most useful Orchard extension points

Tags: orchard, module, development

After some time spent developing Orchard modules I found many useful, yet not documented extension points you can use when writing your own Orchard-based apps. Mentions of many of them are scattered throughout the Orchard discussion board so I made an effort to put them all in one place.

Although in most cases you won’t use all of those features in a single app, knowledge of what you can do can be useful when building more complex, custom, Orchard-based applications.

Note: As far as I have seen the naming convention states that interfaces ending with “Service” are single instance, so if you create the custom implementation, it will be the one used across the whole app. In contrast, interfaces ending with “Provider” mark objects that are thought to provide additional functionality and cooperate with other existing ones, so to be used and injected as an IEnumerable<ISomeProvider>.

Authentication and authorization

Navigation

  • INavigationProviderprovides additional menu items to be merged into the named menu. Implementations can be found almost in every module, which adds menu items to the Dashboard (e.g.. in Orchard.Blogs).

Messaging

  • IMessagingChannel – defines a channel for sending messages from Orchard. Orchard.Email defines the only one – “email” messaging channel, but you are free to create your own. After creating a custom channel you’d be able to force Orchard to use it by default by choosing it as a default one in Site settings.

Request filters

  • FilterProvider – defines the filter applied to each request. Resembles the way default ASP.NET MVC action filters work with the difference that it’s not an attribute. All FilterProvider objects are injected into the request pipeline and are applied to all requests (so you need to check if the current request is suitable for your filter at the beginning of an appropriate method).
  • As with the default ASP.NET MVC filters, your filter also has to implement one (or more) of the following interfaces: IActionFilter, IAuthorizationFilter, IResultFilter, IExceptionFilter. Check those as an example: AdminFilter, ThemeFilter, SecurityFilter.

Display shapes

  • IShapeTableProvider – allows you to programmatically describe your own shapes. Shapes from shape table providers are merged with the dynamically discovered ones (from .cshtml files). Check the CoreShapes definition as an example.

Background tasks

  • IBackgroundTaskdefines the task, which will be run in the background in specified time intervals. It’s Sweep() method will be called every 1 minute (hardcoded in Orchard.Tasks.SweepGenerator). Chris Bower wrote a nice article about that.
  • IScheduledTask – defines the task, which will be run once at a specified time. You can create new tasks via IScheduledTaskManager – just inject this as a dependency and use inside your task-creating objects.
  • IScheduledTaskHandler – defines the processing logic for your custom defined scheduled tasks (look at Orchard.PublishLater module for example).

Data storage

  • IRepository<T>defines the interface for data storage. By default Orchard uses NHibernate to store items in the DB, but you are free to define your own storage logic for specific items. Just implement this interface for the object type you'd like to store an it will override the default one.

 

Orchard delivers a lot more extension points you can make use of. I tried to describe the ones I found the most useful. If you found some other useful ones not described here, fell free to post the info about them in comments – I’ll update the list above.

If the list becomes full enough – I’ll make an effort to place it in the official documentationUśmiech

Cheers!

7 Comments

  • Martin said

    I like the way you think.

    I'm all new to Orchard but aiming to create an integration to a business system (you have to start somewhere, right?). Implementing repositories feels like a fairly easy way of mapping data (at least I'll see where it leads me while trying).

    But beeing a newbie, where would you recommend actually registering my new classes? Autofac encourages programmatic registration (which I definitely agree on), so I'd rather not use the host.config.

    Is there a standard procedure for this that won't be overwritten by an update of Orchard? Idealy, the integration should be installed as one or more module(s), but is it possible to register fundamental stuff like storage that "late" in terms of execution?

    Sorry for the verbose comment.

    /Martin

  • pszmyd said

    @Martin: Thanks:) Writing your own repositories is one of the ways you can take in such scenario.

    I'll advise you check this question on StackOverflow, where I described the easier way (in most cases): http://stackoverflow.com/questions/4727843/how-to-change-orchard-record-repository/5086069#5086069

    About registration - you don't need to register anything with the Autofac directly. You should be able to create your own 'injectable' repository by implementing IDependency interface in addition to IRepository. Orchard registers IDependency objects automatically (by scanning assemblies), so your repository would override the default one (coming from open generic type Repository<> implementation).

    Remember though that implementing your own repository is a lot of work and if you don't have to, I'd recommend using the solution from StackOverflow.

    Cheers!

  • Martin said

    Thanks for answering.

    Born stubborn, I could not just take your word for it and had to check out what it takes to implement a repository since it seemed so conceptually attractive.

    It seems like one would have to start with developing a Linq-provider for the "connected" system. I digged into that and could only conclude that it is, as you so well put it, "a lot of work" (and even if it is done, how would a beast like that remain bug free after changes? I cannot even imagine the amount of unit tests needed...).

    I'll check out your suggested sollution.

    /Martin

  • pszmyd said

    @Martin: Hi! I tried to be concise and yes, by saying "a lot of work" I had "writing a LINQ-provider, which is really nasty" on my mind:) It is attractive, but should be used only, when you really have to.

    But I also think that in such situation, when there is that level of data storage customization needed, it would be easier to customize the query-building stuff underneath to suit your needs, though.

    And BTW - customizing a data layer is a topic for a whole new article(s). I'm getting into it as recently an idea came to my mind to try running Orchard on NoSQL (Raven/Mongo) databases. If I'll make it happen it will surely end with an article or two:)

    Cheers!