SubControllers are MVC Controllers that are also parameters to your action methods. Incorporating their use in large systems allows for composition, dependency inversion, and separation of concerns.
Sometimes we want Controller actions to pass objects into SubControllers so that the SubControllers can do interesting things with them.
For example, in a Product Controller we have the Product, and in a SubController we want to find a few Customers that have recently purchased that Product. We don’t want to call the Customer Repository in the Product Controller – instead we want to pass the Product to the SubController and let it handle talking to the Customer Repository.
It’s easy to give the SubController a public property that the host Controller action can set.
public interface ISubController<T> : ISubController { T Model { get; set; } } public abstract class SubController<T> : SubController, ISubController<T> { public virtual T Model { get; set; } }
To test this we need to be able to mock the RecentCustomersStubController so that we can assert that Model was set with the product object.
[Test] public void Should_set_Model_property_of_SubController_with_product() { var product = new Product(); var subcontroller = MockRepository.GenerateMock<IRecentCustomersSubController>(); var controller = new ProductController(); controller.List(product, subcontroller); subcontroller.AssertWasCalled(s => s.Model = product); }
To create a mock (with Rhino Mocks) we need to extract an interface from the SubController:
public class ProductController : Controller { public ViewResult List(Product product, IRecentCustomersSubController recentCustomers) { recentCustomers.Model = product; return View(); } } public interface IRecentCustomersSubController : ISubController<Product> { } public class RecentCustomersSubController : SubController<Product>, IRecentCustomersSubController { private readonly ICustomerRepository _customerRepository; public RecentCustomersSubController(ICustomerRepository customerRepository) { _customerRepository = customerRepository; } public ViewResult RecentCustomers() { Customer[] recentCustomers = _customerRepository.GetRecentCustomersOfProduct(Model); ViewData.Add(recentCustomers); return View(); } }
3 Responses
Reflective Perspective - Chris Alcock » The Morning Brew #185
23|Sep|2008 1[...] Passing objects to SubControllers – Matt Hinze gives a code example of using the new ASP.NET MvcContrib feature, SubControllers [...]
felix
23|Sep|2008 2Great input really interessting stuff. I would like to have more information about that. Is there a chance to get any sample code. Or extend the sample of the previous article. Thanks anyway… I hope subcontroller or something similar will make into ASP.NET MVC…
Dew Drop - September 23, 2008 | Alvin Ashcraft's Morning Dew
23|Sep|2008 3[...] Passing Objects to SubControllers (Matt Hinze) [...]
Leave a reply