Saturday, March 29, 2014

Startup code in Orchard module

If you work with some CMS it will be better if you will play by its rules. E.g. in Sharepoint basic way to add customizations is feature. It allows you to add custom functionality to the site. In Orchard the basic way to apply customization is module. There may be a lot of custom modules in your project and the more each module will be independent from others the easier maintenance will be.

In the module you may also implement custom functionality like controllers, views and models. Some of this functionality may require adding of initialization code (like adding custom model binder), which in regular ASP.Net MVC application goes to global.asax.cs Application_Start() method. Orchard has own global.asax, but it is located in the common Orchard.Web project which is not related with your module. Is there a way to add initialization code which will be executed on startup for the module? Yes, and it is quite simple. In order to do it we need to add a class which inherits Autofac.Module class to the module’s project (Autofac is IoC library used in Orchard) and override its Load method:

   1: public class ContactFormModule : Module
   2: {
   3:     private bool isInitialized = false;
   4:     protected override void Load(ContainerBuilder builder)
   5:     {
   6:         if (!this.isInitialized)
   7:         {
   8:             ModelBinders.Binders.Add(typeof (FooModel), new FooModelBinder());
   9:             this.isInitialized = true;
  10:         }
  11:     }
  12: }

And that’s basically all. Orchard will automatically wire it up and call during application initialization.

1 comment:

  1. Just came across this, although this was 2 years ago, I thought of leaving my 2 cents. Autofac.Module seems like an overkill which I'd only use when registering new types to resolve.

    Speaking of "playing by rules", Orchard has "IOrchardShellEvents" and "IFeatureEventHandler" which derive from "IDependency". You can hook into IOrchardShellEvents.Activated as follows:

    public class OrchardShellEvents : IOrchardShellEvents
    private readonly IFooModelBinderProvider _fooModelBinderProvider;

    public OrchardShellEvents(IFooModelBinderProvider fooModelBinderProvider)
    _fooModelBinderProvider = fooModelBinderProvider;

    public void Activated()
    ModelBinders.Binders.Add(typeof (FooModel), _fooModelBinderProvider.GetBinder());

    public void Terminating()
    //Do nothing

    It even supports constructor injection.