Found myself looking to wire up TinyIoC container with ASP.NET MVC today. I’d been meaning to have a look see at Tony Sneed’s Trackable Entities. After reviewing an ASP.NET MVC application attempting to leverage theses patterns I knew there was a cleaner approach. I began refactoring the implementation, then realized after reading Tony Sneed’s Trackable Entities now with Repository and Unit of Work patterns that I was rebuilding a similar implementation. Having a personal disdain for not reinventing the wheel, I decided to take a closer look at Tony’s implementation. I like his structure but feel it is lacking a service layer, and state management could be abstracted a bit more but overall liked what I was seeing. In his simple contrived example he already supported ASP.NET WebAPI but my current requirement is to support ASP.NET MVC. Tweaking the implementation was simple enough using the built in MCV scaffolding and tweaking the TinyIoC configuration. In my simple prototype I extended the TinyIoC configuration to support ASP.NET MVC too.
A quick note concerning TinyIoC core design principals.
- Simplified Inclusion – No assembly to reference, no binary to worry about, just a single cs file you can include in your project and you’re good to go. It even works with both Mono and MonoTouch for iPhone development!
- Simplified Setup – With auto-resolving of concrete types and an “auto registration” option for interfaces setup is a piece of cake. It can be reduced to 0 lines for concrete types, or 1 line if you have any interface dependencies!
- Simple, “Fluent” API – Just because it’s “Tiny”, doesn’t mean it has no features. A simple “fluent” API gives you access to the more advanced features, like specifying singleton/multi-instance, strong or weak references or forcing a particular constructor.
Features
- Wide platform support – actively tested on Windows, Mono, MonoTouch, PocketPC and Windows Phone 7. Also works just fine on MonoDroid.
- Simple API for Register, Resolve, CanResolve and TryResolve.
- Supports constructor injection and property injection. Constructors are selected automatically but can be overridden using a “fluent” API.
- Lifetime management – including singletons, multi-instance and ASP.Net per-request singletons. see more features here
The Code
The core TinyIoC Nuget package, Install-Package TinyIoC
is bare bones. However, to leverage ASP.Net per-request lifetime support you will need to also include TinyIoCAspNetExtensions.cs, and the TinyIoC namespace. This provides an extension method for supporting per-request registrations. It’s an extra file, but it’s preferable to taking a dependency on Asp.Net in the main file, which then requires users to setup #DEFINEs for non-asp.net platforms. Recommend installing TinyIoC.AspNetExtensions Nuget package Install-Package TinyIoC.AspNetExtensions
too. I suggest you work through Tony Sneed’s simple Getting Started Guide for Trackable Entities with Repository and Unit of Work Patterns for more context.
Tony defines an IoCConfig.cs
class to handle obtaining a reference to the TinyIoC container, registering types in the container and then setting ASP.NET WebApi Dependency Resolver to the TinyIoCDependencyResolver passing in the TinyIoC container. What you may have already realized is, the dependency resolver is specific to ASP.NET WebApi. Meaning ASP.NET MVC is not currently aware of the TinyIoC container with our new registrations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Create a new Api folder in WebApi project then move the ApiControllers to that folder updating the namespace appropriately. Then use ASP.NET MVC 5 scaffolding to create a new CustomerController
in the default Controller
folder, selecting Async, and Customer model. To quickly prove ASP.NET MVC has no idea about the TinyIoC container create a constructor for CustomerController
show below that injects a INorthwindUnitOfWork dependency. Compile the application, hit F5 to run then navigate to /customer
to blow up the controller.
1 2 3 4 5 6 7 8 9 10 |
|
The good news is updating the configuration to support both ASP.NET WebApi and MVC with same TinyIoC container takes a couple straight forward steps.
- Create a new TinyIocMvcDependencyResolver class that implements System.Web.Mvc.IDependencyResolver
- Update IoCRegister method
- Remove the parameter
- Set ASP.NET MVC Dependency Resolver by adding the line
System.Web.Mvc.DependencyResolver.SetResolver(new TinyIocMvcDependencyResolver(container))
- Set ASP.NET WebApi Dependency Resolver by adding the line
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new TinyIocWebApiDependencyResolver(container);
- Update Global.asax.cs to register TinyIoC using
IoCConfig.Register()
instead ofGlobalConfiguration.Configure(IoCConfig.Register)
Before continuing, assuming you are following along with Tony’s example, I suggest renaming TinyIoCDependencyResolver
class to show intent and be more readable using ReSharper; rename from TinyIoCDependencyResolver
to TinyIocWebApiDependencyResolver
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
|
Leverage Resharper shortcut keys, put cursor on DependencyResolution
folder and use Ctrl+Shift+A
to add a new class called TinyIocMvcDependencyResolver
then copy the code below. This class will be used by ASP.NET MVC to resolve the custom TinyIoC container.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Now update the IoCConfig.cs
class as seen below.
- Remove the parameter
- Set ASP.NET MVC Dependency Resolver by adding the line
System.Web.Mvc.DependencyResolver.SetResolver(new TinyIocMvcDependencyResolver(container))
- Set ASP.NET WebApi Dependency Resolver by adding the line
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new TinyIocWebApiDependencyResolver(container);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Finally the line registering the TinyIoC with ONLY the ASP.NET WebApi GlobalConfiguration.Configure(IoCConfig.Register)
can be replaced with a global registration, IoCConfig.Register()
to register TinyIoC with both ASP.NET MVC and WebApi. Recompile, hit F5, then navigate to /api/customer
to ensure ASP.NET WebApi finds TinyIoC container, then navigate to /customer
to ensure ASP.NET MVC now can find TinyIoC container too.
1 2 3 4 5 6 7 8 9 10 11 |
|