Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting dependency into MVC controller with Spring .NET

The object in the controller is not getting injected at run time.

Web.config:

    <sectionGroup name="spring">
        <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
        <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>

. . .

<!-- Spring Context Configuration -->
<spring>
    <context>
        <resource uri="config://spring/objects"/>
    </context>
    <objects configSource="App_Config\Spring.config" />
</spring>
<!-- End Spring Context Configuration -->

Spring.config:

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">

    <!-- Crest is the WCF service to be exposed to the client, could not use a singleton -->

    <object id="TestController" type="Project.Controllers.TestController, Project" singleton="false">
        <property name="ObjectA" ref="ObjectImpl"/>
    </object>

    <object id="ObjectImpl" type="Project.Code.Implementations.ClassA, Project" singleton="false" />

</objects>

TestController:

public class TestController: Controller
    {
        // this object will be injected by Spring.net at run time
        private ClassA ObjectA { get; set; }

Problem:

At runtime the ObjectA does not get injected and stays null, which cause null exception throughout the code.

Alternative: I can manually initialize the Spring object and get it's object using the following code.

        var ctx = ContextRegistry.GetContext();
        var objectA = ((IObjectFactory)ctx).GetObject("ObjectImpl") as ClassA;
like image 939
Jun Zheng Avatar asked Oct 06 '22 17:10

Jun Zheng


2 Answers

It turns out I was missing a pretty important part of Spring Implementation for MVC.

My solution to the problem was by adding a DependencyResolver which implements the IDependencyResolver.

DependencyResolver:

public class SpringDependencyResolver : IDependencyResolver
{
    private readonly IApplicationContext _context;

    public SpringDependencyResolver(IApplicationContext context)
    {
        _context = context;
    }

    public object GetService(Type serviceType)
    {
        var dictionary = _context.GetObjectsOfType(serviceType).GetEnumerator();

        dictionary.MoveNext();
        try
        {
            return dictionary.Value;
        }
        catch (InvalidOperationException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
            return _context.GetObjectsOfType(serviceType).Cast<object>();
    }
}

Global.asax.cs:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        DependencyResolver.SetResolver(new SpringDependencyResolver(ContextRegistry.GetContext()));
    }
like image 121
Jun Zheng Avatar answered Oct 10 '22 01:10

Jun Zheng


You can implement your own IDependencyResolver, like you suggest in your answer. Please note however that since (iirc) version 1.3.1 Spring.NET has built-in support for asp.net mvc 2.0 and 3.0. Spring.net 2.0 (pre release available on NuGet) has built in support for version 4.0 too. Consider using these libraries instead.

You might be interested in comparing your SpringDependencyResolver to the the one provided by the Spring.net team.

like image 24
Marijn Avatar answered Oct 10 '22 03:10

Marijn