Regarding number 1:
IConfigurableModule is a special kind of IInitializableModule (as you pointed out the interface is inherited). What it adds in addition is a method ConfigureContainer (which is called once during initialization before Initialize), in the implementation you are able to add/register your custom abstractions to the IOC container through context.Container.
In MVC there is a possibility to define your own DependencyResolver, you can see in the class DependencyResolverInitialization (in the template project) that a implemenation that uses the StructureMap container is registered.
Hi Johan and thanks for your answer. I looked into the implementation of the DependencyResolverInitialization and I think I understand it. However I have some followup question that if I am lucky you have time to answer.
1. The parameter sent into the ConfigureContainer method is of type ServiceConfigurationContext. I assume that one is sent in from the framework during the initialization process. The Container property of ServiceConfigurationContext is of type IContainer which seems to be a StructureMap specific interface declared in namespace StructureMap. Does that mean that EPiServer uses StructureMap as IoC container and that can't be changed to another IoC container ( if I for some reason would want that )?
2. In my original question I asked about how the parameters to the controller PreviewController could be resolved. Perhaps you answered that implicitly in your answer by saying that StructureMap was used (in the template project), and I just did not understand it =) . But is that the case, is it StructureMap that is responsible for injecting the correct parameters to the previewcontroller in this case? Because I can't see any configuration in DependencyResolverInitialization that is related to parameters sent to controllers. Does that happen "magically" under the hoods and there is no need for an explicit configuration file or similar? If that is the case I need to do some reading of StructureMap =)
It is correct that EPiServer uses StructureMap internally and you are not supposed to change the IOC container that is used internally. You can however have your own IOC container for your own abstractions if you like.
It is also only in ConfigureContainer that the StructureMap container is exposed, otherwise when retieveing instances from container you normally use IServiceLocator interface which is an abstraction over container implementations. So for EPiServer it would probably be possible to change IOC container without more than a minor breaking change.
And in theory it would probably be possible to exchange StructureMap container toward another container by listening to e.g. InitCompleted and in there read all registrations from structureMap and register them in another container and then set ServiceLocator.Current to the new container. But this is just in theory and nothing we support officially....
If you put a breakpoint in the constructor you can see from the stacktrace that the code originates from System.Web.Mvc.DefaultControllerFactory which then calls the registered DependencyResolver (in our case StructureMapDependencyResolver) to resolve the dependencies.
So the "magic" is really the line
in class DependencyResolverInitialization. There is where we register our custom dependency resolver with MVC. Then MVC will use that to resolve dependencies e.g. when creating controller instances.
Thanks Johan for great answers!
I looked into structureMap yesterday and thanks to your explanation and some reading things are starting to make more sense. However there are still a couple of things that I don't fully understand and hopefully you can ( once again ) help me put some light on them =) I'm not sure if it was the correct way to continue this thread when I had marked it as resolved but I did that instead of starting an new one.
1. In PreviewController it takes two parameters (IContentLoader contentLoader, ContentAreaRowBalancer rowBalancer). Where does the registration happen? With registration I mean the part x.For<IContentLoader>().Use<ContentLoader>(); or however is it defined in this case. Does the registration for IContentLoader happen inside "native" EPiServer code?
2. But the ContentAreaRowBalancer is declared outside EPiServer "native" code, but I can't see any registration for it. I was expecting to see a x.For<ContentAreaRowBalancer>().Use<ContentAreaRowBalancer>(); or similar somewhere in the code. Isn't this part necessary so the container knows what to inject?
StructureMapDependencyResolver basically just wraps StructureMap here so I assume there had to be some registration going on. Am I missing some elementary logic here, is there some autowiring happening here or where does all the registration occur?
1. IContentLoader is part of EPiServer CMS and hence is the default implementation of the interface registered as part of the initialization of CMS itself.
2. Concrete classes as ContentAreaRowBalancer does not need to be explicitlty registered with the container. The container can resolve instances of concrete classes anyway and will use the constructor with most parameters and locate the parameter dependencies within the container.
As alternative to explicitly register entries in container like:
you can use attribute ServiceConfiguration attribute like example below:
public class ContentDataBuilder : IContentDataBuilder
During initialization EPiServer will scan for all types with the attribute and do the registration with IOC container.
Thanks again! Now I finally get it =)
Excellent post, but can I just ask, Is it necessary to Set the dependencyResolver with:
I presume that EPiServer has already set the dependency resolver and so I am merely configuring the container in my IConfigurableModule with
This works ok on my machine but my colleague gets
StructureMap Exception Code: 202 No Default Instance defined for PluginFamily IMyInterface ....
I was afraid that if I re set the dependency resolver, then I would loose the default dependency resolver setup by EPiServer ?
Is this the case ?
Is re-setting the dependency resolver with your own implementation best practice ? Or why would you need to do it, if EPiServer already sets it for you ?
The dependency resolver is set by the template project EPiServer.Templates.Alloy.Mvc (so it is not set in CMS it self), that means that if you are building your templates based on that project it will be set for you. If you however build your own templates then you need to set it your self.
Hi, I have some questions regarding MVC in EPiServer that I don't really understand. If a question is to "big" to answer in an easy way I would really appreciate if someone could provide a link to where I can read more about the relevant topic. I have had problems finding information for some topics but that may be me that is just bad at finding information =)
I have been looking on Joel Abrahamsson's excellent article "ASP.NET MVC Templates for EPiServer 7 CMS" and been trying to understand the code and how things actually works but there is some parts that I don't really understand. I'm quite new to both asp.net and to EpiServer ( but not to programming) so please bear with me if some questions seems "stupid".
1. First a question about initialization. I have read in the developer guide that to have a discoverable initialization module the class has to be decorated with [InitializableModule] or [ModuleDependency(...)] and implement the interface IInitializableModule. If those criterias are met the class implementing the methods in IInitializableModule are executed during startup automagically from the framework. This is all logic and described in the developer guide. However in the code for the "MVC Templates" there is class defined as below
public class DependencyResolverInitialization : IConfigurableModule
public void ConfigureContainer(ServiceConfigurationContext context)
The Interface IConfigurableModule implements IInitializableModule so its logic that it will be discovered during the initialization phase. However I assume the method defined IConfigurableModule called ConfigureContainer is also executed during startup? Am I supposed to understand that due to the fact that it implements IInitializableModule and therefore ConfigureContainer is called as well or am I missing something else here? Is there any documentation about this, or am I just bad at finding things? The parameter sent in, ServiceConfigurationContext context, is that a reference to the actual IoC-container then ( which if I understood it right is StructureMap )?
2. Another question, possibly related to IoC and StructureMap. In the "MVC Templates" there is Controller called PreviewController which has a constructor that looks like below:
public PreviewController(IContentLoader contentLoader, ContentAreaRowBalancer rowBalancer)
_contentLoader = contentLoader;
_rowBalancer = rowBalancer;
How are the parameters sent into that constructor resolved? The way I understood it asp.net could map parameters from an incoming request to parameters named the same way in the function signature or in properties named the same in some wrapping class. But in this case I can't see how that can happen? Is there some configuration file somewhere that configures things like this or is there some magic happening somewhere? I'm not even sure what is responsible for this, is it asp.net, episerver or some IoC functionality?
Hope someone can help me to put some light on these topics. If I seem to lack some elementary knowledge here please point me in the right direction for where to read up. It's hard but fun to learn new things =)