Integrating EPiServer 7 With an Existing MVC Site
This post assumes you have EPiServer 7 installed on your machine. If you don’t have it then it is available from EPiServer world (once you have created an account).
There are 2 main options for creating a new EPiServer 7 MVC stylee site:
- Create a new Visual studio project (after installing ‘EPiServer 7 Visual Studio Integration’, available from EPiServer world)
- Use the EPiServer 7 MVC templates package
For integrating with an existing site I’d recommend using option 1, as there are far less files to integrate. However it is well worth looking at the templates package as well as this demonstrates how models and views can be implemented with EPiServer 7.
After creating the new Visual Studio project I remembered that EPiServer have a NuGet feed, and they do have the version 7 assemblies on NuGet. However the version numbers are slightly different to those used in the visual studio project, so make sure you specify the version numbers to NuGet when you install the packages (they are listed below). Here are the steps I followed in detail:
- Created a new Visual studio project using the EPiServer Web Site (MVC) template
- Followed the EPiServer tutorial (link) to add a home page and set it to the ‘start page’
- Upgraded my existing site to MVC 4 by installing the Microsoft ASP.NET MVC 4 nuget package (obviously not required if your existing site is already on MVC version 4.
- Copy across the connectionStrings.config, episerver.config, EPiServerFramework.config, EPiServerLog.Config and FileSummary.config files
- Update the siteUrl in episserver.config.
- Copy the AppData, IndexingService, modules and modules bin folders.
- Merge the web.config files - ensure the episerver.search baseUri is updated to point at your site address.
- Installed EPiServer 7 from Nuget feeds using these commands to get the correct versions:
- Install-Package EPiServer.Framework -Version 7.0.859.1
- Install-Package EPiServer.CMS.Core -Version 7.0.586.1
- Removed assembly references to Razor and System.WebPages.Razor (as was clashing with EPiServer versions)
- Update Controllers to inherit from PageController<T> where T is a PageData class.
- Update Global.asax to inherit from EPiServer.Global
IoC containers clashing!
OK, this is the tricky bit it gets quite involved but please stay with me!
When I tried to run the site it now returned a ‘No parameterless construct or defined for this object.’ message. Which in plainer English means the application can’t create the Controller classes. This is because the site I am integrating with currently uses the Castle Windsor IoC container, however EPiServer uses the StructureMap IoC container internally. We definitely don’t want two IoC containers and I can’t see any evidence of the EPiServer container being swappable. So the only option here is to convert the current Windsor implementation to a StructureMap implementation. More information on Structure map can be found on the excellent StructureMap documentation site, however I think it is worth including an overview in this post as, whilst this isn’t always going to be necessary for your site, I expect it will be a common problem.
Add StructureMap version 18.104.22.168
This is available from NuGet (as this is the version used in the EPiServer 7 MVC templates package). The command to install is: Install-Package StructureMap -Version 22.214.171.124
Register your services with StructureMap
- Copy the StructureMapDependencyResolver and DependencyResolverInitialization classes from the EPiServer MVC templates project.
- Convert service registration calls to register services with StructureMap instead of Windsor. This is carried out in the ConfigureContainer method of the DependencyResolverInitialization class.
For example here is a Windsor interface registration and its equivalent StructureMap registration:
//Windsor registration - Here container is an implementation of IWindsorContainer var myConfig = WebConfigurationManager.GetSection("myConfig") as MyConfig; container.Register(Component.For(typeof(IMyConfig)).Instance(myConfig));
//StructureMap registration - Here container is of type ConfigurationExpression var myConfig = WebConfigurationManager.GetSection("myConfig") as MyConfig; container.For<IMyConfig>().Use(myConfig);
An example of a class registration with a singleton lifestyle:
//Windsor registration container.Register(Component.For(typeof(Cache)).Instance(HttpContext.Current.Cache).LifestyleSingleton());
//StructureMap registration container.For(typeof(Cache)).Singleton().Use(HttpContext.Current.Cache);
- Convert IWindsorInstaller implementations to Registry subclasses.
Debugging your StructureMap registrations
You can debug structure map by adding this line:
Initially EPiServer was reporting many registration failures but you can delay the call until the InitComplete event is called in the DependencyResolverInitialization class. Then most of the EPiServer registrations have completed and it is easier to see if there are any issues with your own services.
Manually retrieving a service
Generally my services are injected into constructors automatically, however I had a couple of calls to retrieve services manually from the IoC container. For example, to retrieve an implementation of an interface called IMyService:
_var myService = DependencyResolver.Current.GetService<IMyService>();
Hopefully your site will be running now, there is some additional configuration work you may want to do for EPiServer 7 VPP folders. But if you’ve made it this far you will probably need a break!
Updated on 9th April 2013
Updated the list of config files which must be copied to include EPiServerLog.config and FileSummary.config