The Spring.NET for ASP.NET MVC Infrastructure increases your productivity when you write ASP.NET MVC 2.0 applications by making the full power of the Spring.NET framework available to your MVC projects.
Highlights of the Spring.NET for ASP.NET MVC Infrastructure (also referred to in this document as Spring.Web.Mvc) are:
Dependency Injection of Controllers and ActionFilters. ASP.NET
MVC 2.0 provides two primary extensbility points for Dependency
Injection: Controllers
and
ActionFilters
. Spring.Web.Mvc makes it extremely
simple to inject dependencies into either your MVC
Controllers
or ActionFilters
.
Simply register your Controllers
and
ActionFilters
with the context using any one of the
typical object definition approaches supported by Spring.NET and the
Spring.Web.Mvc infrastructure will ensure these objects are assembled
correctly when the ASP.NET MVC run-time has need of them.
Web object scopes. Just as with the Spring.NET Web Infrastructure for ASP.NET Webforms, Spring.Web.Mvc objects can be defined at the application, session, or request scope. This capability makes it easy to inject, for example, a session scoped shopping cart, into your controllers without any lower level programming.
The Spring.NET distribution ships with a Web.Mvc Quick Start application. The Web.Mvc QuickStart is the best way to see how to integrate Spring.Web.Mvc into your own ASP.NET MVC applications.
Spring.Web.Mvc builds on top of the Spring.NET IoC container.
Controllers
and ActionFilters
that
make up a typical Spring.Web.Mvc-enabled application are configured with
the same standard Spring.NET XML configuration syntax used for non web
objects. To integrate with the ASP.NET MVC runtime you need to make a
few modifications to your Web.config
file and your
Global.asax
.
The instantiation and configuration of the Spring.NET IoC
container by the Spring.Web.Mvc infrastructure is wholly transparent to
application developers, who typically never have to explicitly
instantiate and configure an IoC container manually (by, for example,
using the new
operator in C#). To effect the
transparent bootstrapping of the IoC container, you need to modify the
primary Application
class in the
Global.asax
so as to derive it from the special
SpringMvcApplication
class as shown in the following
snippet:
public class MvcApplication : SpringMvcApplication { }
Note that the SpringMvcApplication
class is
abstract so that developers may only use it indirectly as a superclass
of their own global application class in the
Global.asax
of their ASP.NET MVC applications.
After the Global.asax
is modified as indicated
above, you also need to define a root application context by adding a
Spring.NET configuration section to your Web.config
file. The final configuration file should resemble the following; your
exact configuration may vary in particulars and the following snippet
illustrates only the Spring-specfic entries and excludes the remainder
of the content (typically) required by ASP.NET MVC.
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.MvcContextHandler, Spring.Web.Mvc"/> </sectionGroup> </configSections> <spring> <context> <resource uri="~/Config/Controllers.xml"/> <resource uri="~/Config/Filters.xml"/> <resource uri="~/Config/Production/Services.xml"/> <resource uri="~/Config/Production/Dao.xml"/> </context> </spring> </configuration>
Notes about the preceding configuration:
Define a custom configuration section handler for the
<context
>
element. If you use
Spring.NET for many applications on the same web server, it might be
easier to move the whole definition of the Spring.NET section group
to your machine.config
file.
The custom configuration section handler is of the type
Spring.Context.Support.MvcContextHandler
which in
turn instantiates an IoC container of the type
Spring.Context.Support.MvcApplicationContext
.
This ensures that all features provided by Spring.Web.Mvc, such as
request and session-scoped object definitions, are handled
properly.
Within the <spring>
element, define a root
context element. Next, specify resource locations that contain the
object definitions that are used within the web application (such as
service or business tier objects) as child elements within the
<context> element. Object definition
resources can be fully-qualified paths or URLs, or non-qualified, as
in the example above. Non-qualified resources are loaded using the
default resource type for the context, which for the
MvcApplicationContext
is the
WebResource
type.
The object definition resources do not have to be the same
resource type (for example, all file://
, all
http://
, all assembly://
, and
so on). This means that you can load some object definitions from
resources embedded directly within application assemblies
(assembly://
) while continuing to load other
object definitions from web resources that can be more easily
edited.
The default behavior, settings, ASP.NET MVC start-up related and
Spring.NET container-configuration behaviors can be modified and
controlled by overriding various methods of the
SpringMvcApplication
in your own derived instance.
The following section describes these overridable methods and their
existing behavior provided in the base
SpringMvcApplication
class. Please note that if you
choose to override any of these methods and do not subsequently invoke
the base SpringMvcApplication
class' implementation
of that same method, then you are completely responsible for ensuring
that the underlying reponsibilities of that method in the base class are
satisfied by your overloaded implementation. Without either ensuring
this or invoking the base class implementation within your overridden
method, the underlying behavior of the ASP.NET MVC runtime (and its
integration with Spring.NET) is unlikley to function as intended.
This method is provided by the Microsoft base
HttpApplication
class and is overridden in the
SpringMvcApplication
base class to be responsible
for invoking the RegisterRoutes()
and RegisterAreas()
methods. If you choose to override the
Application_Start()
implementation of the
SpringMvcApplication
class in your own
implementation, ensure that you either call
base.Application_Start()
or explicitly invoke both
the RegisterRoutes()
and RegisterAreas()
methods within your within your override of this method.
This method is invoked by the
SpringMvcApplication
class after it has been
configured with all of its object definitions and other settings (as
detailed in Configuration of a
ASP.NET MVC Application) but immediately prior to its being
handed off to the ASP.NET MVC infrastructure for its use. Overridding
this method provides you with your last possible moment to make any
additional modifications to the IApplicationContext
before it is put into service for the ASP.NET MVC framework's use. In
the SpringMvcApplication
base class, this method is
a no-op and thus does nothing. It exists only to provide an
extensibility point for developers wishing to interact with the
IApplicationContext
at this point in the
application startup/context configuration lifecycle.
This method is responsible for registering the
SpringControllerFactory
with the ASP.NET MVC
framework, in effect telling ASP.NET MVC "please use the
SpringControllerFactory
to create
Controllers
." This is the manner in which the
Spring.NET container is subsequently invoked to satisfy dependencies
on Controllers
when they are instantiated by
ASP.NET MVC in response to an Http Request. Generally, there should be
little need for the developer to override this method, but if you do
you must ensure that your either invoke the base implementation of
RegisterSpringControllerFactory()
from within your
implementation or that you explicitly register the
SpringControllerFactory
with the ASP.NET MVC
infrastructure yourself from witihin this method (or elsewhere at the
appropriate time).
This method is responsible for registering ASP.NET MVC Routes
during application startup and is automatically invoked from within
the Application_Start()
method in the SpringMvcApplication
base class. The
provided implementation of this method in the
SpringMvcApplication
class merely registers the
same Default
route as is present in any new ASP.NET
MVC project that Visual Studio creates (e.g.,
"{controller}/{action}/{id}
"). As such it is
expected that most developers will override this method and provide
their own implementation wherein they will register their own routes.
Unless you desire to retain the out-of-the-box
Default
routing configuration of
"{controller}/{action}/{id}
" it is not necessary
for developers to call the RegisterRoutes()
method
of the SpringMvcApplication
base class from within
their own overrides of this method.
This method is responsible for registering ASP.NET MVC Areas
during application startup and is automatically invoked from within
the Application_Start()
method in the SpringMvcApplication
base class. The
provided implementation of this method in the
SpringMvcApplication
class merely invokes
AreaRegistration.RegisterAllAreas()
in the ASP.NET
MVC framework. As such, it is not common to have to override this
method as provided in the SpringMvcApplication
base
class unless you desire more fine-grained control over registering
areas. If you choose to override this method in your own derived
class, you are assuming the responsibility of registering all Areas
with the ASP.NET MVC runtime.
Spring.NET web applications support an additional attribute within object definition elements that allows you to control the scope of an object:
<object id="myObject" type="MyType, MyAssembly" scope="application | session | request"/>
Possible
values for the scope attribute are application,
session, and request
. Application
scope is the default, and is used for all objects with an undefined scope
attribute. This scope creates a single instance of an object for the
duration of the IIS application, so that the objects works exactly like
the standard singleton objects in non-web applications. Session scope
defines objects so that an instance is created for each HttpSession. This
scope is ideal for objects such as user profile, shopping cart, and so on
that you want bound to a single user.
Request scope creates one instance per HTTP request. Unlike calls to
prototype objects, calls to
IApplicationContext.GetObject
return the same instance
of the request-scoped object during a single HTTP request. This allows
you, for example, to inject the same request-scoped object into multiple
pages and then use server-side transfer to move from one page to another.
As all the pages are executed within the single HTTP request in this case,
they share the same instance of the injected object.
Objects can only reference other objects that are in the same or broader scope. This means that application-scoped objects can only reference other application-scoped objects, session-scoped objects can reference both session and application-scoped objects, and request-scoped objects can reference other request-, session-, or application-scoped objects. Also, prototype objects (including all ASP.NET web pages defined within Spring.NET context) can reference singleton objects from any scope, as well as other prototype objects.