Using Spring.NET with MVC 3
by Alex on Mar.07, 2011, under .NET, C#, MVC 3, Spring.NET
With MVC 3 comes the IDependencyResolver interface. This is designed to allow Service Providers to be registered with the framework. Service providers can range from IOC Containers such as Castle Windsor / Spring .NET, View Engines or Filter Providers.
The IDependencyResolver interface has two methods which must be implemented and looks like this:
public interface IDependencyResolver{
public object GetService(Type serviceType);
public IEnumerable<object> GetServices(Type serviceType);
}
The “GetService” method is used when only one service is expected to be returned, such as a controller implementing IControllerFactory. “GetServices” is called when more than one object is expected to be returned such as FilterProviders. If no matches are found GetService must return null and GetServices needs to return an empty set. If anything else is returned in either of these situations an exception will be thrown.
Let’s see how we can create a SpringDependencyResolver that implements the IDependencyResolver interface.
public class SpringDependencyResolver : IDependencyResolver{
private IApplicationContext springContext;
public SpringDependencyResolver(IApplicationContext context){
springContext = context;
}
public object GetService (Type serviceType){
IDictionaryEnumerator di = springContext.GetObjectsOfType(serviceType).GetEnumerator();
di.MoveNext();
try{
return di.Value;
}catch(InvalidOperationException ioe){
return null;
}
public IEnumerable<object> GetServices(Type serviceType){
IDictionary dictionary = springContext.GetObjectsOfType(serviceType);
return dictionary.Cast<object>();
}
}
It’s fairly straight forward, with only a couple of things to note. Line 10 can return a number of items. This is because I couldn’t seem to find any other way in Spring .NET of returning one object for that type, so instead, if more than one is returned we just select the first, as you can see in line 12. The SpringContext does have a GetObject(string name) method, but as you can see, itself and all it’s overloaded versions require the name of the Object. This isn’t specified in IDependencyResolver, so I got around it by returning the first item.
Lines 20 and 21 involve getting the Dictionary from Spring .NET with all the objects and casting it to a dictionary of “Object” types and then returning.
Once you have your SpringDependencyResolver ready, you’ll want to plug it into your app and get going. To register the SpringDependencyResolver, you would normally need to do this in the Global.asax file in the Application_Start() method. This is normally a simple step, but I encountered a problem. It seems that in IIS 7, when running in Integrated mode, the Request scope is not available in the Application_Start() method and Spring .NET needs this scope to initialise itself. You can read more about this here: http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx
So, with the help of Mike Volodarsky in the post above let’s see how we can plug our SpringDependencyResolver into our application. In my Global.asax file I have the following class defined:
class FirstRequestInitialization{
private static bool s_InitializedAlready = false;
private static Object s_lock = new Object();
// Initialize only on the first request
public static void Initialize(){
if (s_InitializedAlready){
return;
}
lock (s_lock){
if (s_InitializedAlready){
return;
}
//Set SpringDependencyResolver as resolver for the framework
DependencyResolver.SetResolver(
new SpringDependencyResolver(ContextRegistry.GetContext()));
s_InitializedAlready = true;
}
}
}
Along with this for my Application_BeginRequest() method:
protected void Application_BeginRequest(Object source, EventArgs e){
/* Attempt to peform first request initialization - To fix issue of
** request scope not being available on App start
*/
FirstRequestInitialization.Initialize();
}
As you can see, the initialization of the SpringDependencyResolver is only fired on the very first request of the application and gets around the issue described in Mike’s post. Of course all your other regular MVC related stuff can go in the Appication_Start() method such as registering filters and routes. It’s only the Spring .NET initialization that needs Mike’s solution.
May 24th, 2011 on 3:11 pm
hi, have you got a zip file with a sample for this?
I would love to download it and have a look at how it works without doing too many copy and paste from your blog
May 24th, 2011 on 3:59 pm
Hi Smnbss,
I don’t have a zip file, but the code you need is all there. Just create a new MVC 3 project, add spring.NET, copy my “SpringDependencyResolver” code and update your Global.asx file as outlined in the post and that should get you going.
Obviously you’ll need to add some spring objects to the web.config such as your controllers to start with, but that is out of this post’s scope. If you want to see how to update the config file for Spring.NET I would head over here: http://www.springframework.net/documentation.html. The documentation on Spring.NET is extensive and well written. If you do have further trouble let me know and I’ll see if I can dig some samples out for you.
May 24th, 2011 on 4:41 pm
done, thanks.
I’m having an exception like
“Cannot instantiate a class that does not have a no-argument constructor”
using a Controller that accept an object in the constructor
spring config looks good to me:
May 24th, 2011 on 5:31 pm
It sounds like the web.config is set to instantiate your controller without the object you mention and because you have specified a constructor that takes an object you no longer have a “no-argument” constructor.
If you add a new parameter-less constructor it should at least run, but it sounds like your controller will be instantiated without the object.
To correctly fix the problem, you need to ensure you have specified the object to be pass through to the controller. Ensure the object you are passing through is also registered with Spring and reference it in the config for your Controller.
July 2nd, 2011 on 4:37 pm
I did the same but still not able to run a simple mvc with spring!
Is this too much ask for a zip file?