Hello,
I've been playing around with MVC v2 (Preview 2) Areas and was running
into some problem using the MvcContrib SpringControllerFactory.
Namely, if you have two areas both of which contain a controller with
the same name --e.g., "Login", Spring was not able to resolve the
correct controller. A small change to the MvcContrib
SpringControllerFactory fixed it which I've posted below in case
anyone else has this issue. (No doubt it something like it will be
folded into McvContrib at some point so this is really just intended
to a temporary fix.)
Hope it helps,
Chad Finsterwald
http://www.blueskycollaborative.com/
New SpringControllerFactory. The changes are to the CreateController
method where I added some simple support for areas.
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Spring.Context;
using Spring.Objects.Factory;
namespace MvcContrib.Spring
{
/// <summary>
/// Controller Factory implementation for Spring.net
/// </summary>
public class SpringControllerFactory : IControllerFactory
{
private static IObjectFactory _objectFactory;
/// <summary>
/// Configures the controller factory to use the
/// given
spring.net IObjectFactory for controller lookup.
/// If you call Configure multiple times, the last call will
prevail.
/// </summary>
/// <param name="objectFactory">IObjectFactory instance to use
for lookups.</param>
public static void Configure(IObjectFactory objectFactory)
{
_objectFactory = objectFactory;
}
/// <summary>
/// Configures the controller factory to use the
/// given
spring.net IApplicationContext for controller
/// lookup. If you call Configure multiple times, the
/// last call will prevail.
/// </summary>
/// <param name="ctx"></param>
public static void Configure(IApplicationContext ctx)
{
_objectFactory = ctx;
}
public IController CreateController(RequestContext context,
string controllerName)
{
if (string.IsNullOrEmpty(controllerName))
throw new ArgumentNullException("controllerName");
string area = string.Empty;
if (context.RouteData.DataTokens.ContainsKey("area"))
{
area = context.RouteData.DataTokens["area"].ToString() ;
}
controllerName = area + controllerName + "Controller";
if (_objectFactory == null)
{
throw new ArgumentException("CreateController has been
called before Configure.");
}
try
{
return (IController)_objectFactory.GetObject
(controllerName);
}
catch (Exception e)
{
throw new InvalidOperationException("Failed creating
instance of: " +
controllerName + " using
spring.net object factory", e);
}
}
public void ReleaseController(IController controller)
{
var disposable = controller as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
}
Spring IOC set-up. Note the convention I've used is to prepend the
name of the area in front of the controller, --e.g. given two area
with the names "Administration" and "Participant" both with a
controller called Login I used the following:
AdministrationLoginController and ParticipantLoginController.
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="
http://www.springframework.net">
<!-- Controllers -->
<object id="HomeController" sing
<object id="SearchController" singleton="false"
type="Main.Controllers.SearchController"/>
<object id="SponsorsController" singleton="false"
type="Main.Controllers.SponsorsController"/>
<object id="ParticipantLoginController" singleton="false"
type="Participant.Controllers.LoginController"/>
<object id="AdministrationLoginController" singleton="false"
type="Administration.Controllers.LoginController"/>
<!-- End Controllers -->
</objects>
</spring>