In an MVC project I'm creating I have the following RequirePermissionAttribute that gets put on any action that needs specific permissions (it's been simplified for this example):
public class RequirePermissionAttribute : ActionFilterAttribute, IAuthorizationFilter
{
public Operation Permissions { get; set; }
public RequirePermissionAttribute() { }
public RequirePermissionAttribute(Operation permissions)
{
this.Permissions = permissions;
}
public bool AuthorizeCore(HttpContextBase httpContext)
{
IAuthorizationService authServ = new ASPNETAuthorizationService();
return authServ.Authorize(httpContext);
}
public void OnAuthorization(AuthorizationContext filterContext)
{
Enforce.ArgNotNull(filterContext);
if (this.AuthorizeCore(filterContext.HttpContext))
{
// code snipped.
}
else
{
// code snipped.
}
}
}
So the problem obviously with this is that my authorize attribute has a dependency on the ASPNETAuthorizationService that I created. I can't go the constructor way since attributes are compile-time checked.
One thing to mention, I'm using my own little IoC that I made and it doesn't have support for property injection (yet). Of course, if I did go the property injection route, I'd have to add support for it (which I'd have to do some research on).
What's the best way to inject something into an attribute class?
What's the best way to inject something into an attribute class?
Strictly speaking, we cannot use dependency injection to inject a dependency into an attribute. Attributes are for metadata not behavior. [AttributeSpecification()] encourages this by forbidding reference types as arguments.
What you're probably looking for is to use an attribute and a filter together, and then to inject dependencies into the filter. The attribute adds metadata, which determines whether to apply the filter, and the filter receives the injected dependencies.
How to use dependency injection with an attribute?
There are very few reasons to do this.
That said, if you're intent on injecting into an attribute, you can use the ASP.NET Core MVC IApplicationModelProvider. The framework passes dependencies into the provider's constructor, and the provider can pass dependencies to the attribute's properties or methods.
In your Startup, register your provider.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Transient
<IApplicationModelProvider, MyApplicationModelProvider>());
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
Use constructor injection in the provider, and pass those dependencies to the attribute.
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
public class MyApplicationModelProvider : IApplicationModelProvider
{
private IUrlHelperFactory _urlHelperFactory;
// constructor injection
public MyApplicationModelProvider(IUrlHelperFactory urlHelperFactory)
{
_urlHelperFactory = urlHelperFactory;
}
public int Order { get { return -1000 + 10; } }
public void OnProvidersExecuted(ApplicationModelProviderContext context)
{
foreach (var controllerModel in context.Result.Controllers)
{
// pass the depencency to controller attibutes
controllerModel.Attributes
.OfType<MyAttribute>().ToList()
.ForEach(a => a.UrlHelperFactory = _urlHelperFactory);
// pass the dependency to action attributes
controllerModel.Actions.SelectMany(a => a.Attributes)
.OfType<MyAttribute>().ToList()
.ForEach(a => a.UrlHelperFactory = _urlHelperFactory);
}
}
public void OnProvidersExecuting(ApplicationModelProviderContext context)
{
// intentionally empty
}
}
Create an attribute with public setters that can receive dependencies.
using System;
using Microsoft.AspNetCore.Mvc.Routing;
public sealed class MyAttribute : Attribute
{
private string _someParameter;
public IUrlHelperFactory UrlHelperFactory { get; set; }
public MyAttribute(string someParameter)
{
_someParameter = someParameter;
}
}
Apply the attribute to a controller or an action.
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[MyAttribute("SomeArgument")]
public class ValuesController : Controller
{
[HttpGet]
[MyAttribute("AnotherArgument")]
public string Get()
{
return "Foobar";
}
}
The above demonstrates one way, for the rare use case, that you can inject dependencies into an attribute. If you figure out a valid reason to do this, please post it in the comments.
I originally thought this was not possible, but I stand corrected. Here's an example with Ninject:
http://codeclimber.net.nz/archive/2009/02/10/how-to-use-ninject-to-inject-dependencies-into-asp.net-mvc.aspx
Update 2016-10-13
This is a pretty old question by now, and frameworks have changed quite a bit. Ninject now allows you to add bindings to specific filters based on the presence of specific attributes, with code like this:
// LogFilter is applied to controllers that have the LogAttribute
this.BindFilter<LogFilter>(FilterScope.Controller, 0)
.WhenControllerHas<LogAttribute>()
.WithConstructorArgument("logLevel", Level.Info);
// LogFilter is applied to actions that have the LogAttribute
this.BindFilter<LogFilter>(FilterScope.Action, 0)
.WhenActionHas<LogAttribute>()
.WithConstructorArgument("logLevel", Level.Info);
// LogFilter is applied to all actions of the HomeController
this.BindFilter<LogFilter>(FilterScope.Action, 0)
.WhenControllerTypeIs<HomeController>()
.WithConstructorArgument("logLevel", Level.Info);
// LogFilter is applied to all Index actions
this.BindFilter(FilterScope.Action, 0)
.When((controllerContext, actionDescriptor) =>
actionDescriptor.ActionName == "Index")
.WithConstructorArgument("logLevel", Level.Info);
This is in keeping with the principle, argued by Mark Seeman and by the author of Simple Injector, which is that you should keep the logic of your action filter separate from the custom attribute class.
MVC 5 and 6 also make it far easier to inject values into attributes than it used to be. Still, separating your action filter from your attribute is really the best approach to take.
Related
I have implemented the IAsyncAuthorizationFilter interface to a class; in addition, that class is derived from Attribute, so that I can mark controller classes and action methods using it. This works so far; the Task OnAuthorizationAsync(AuthorizationFilterContext context) method is called before the action method, and if the request is not authenticated, an HTTP 401 is returned for the response.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class CustomAuthenticationAttribute : Attribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
...
}
}
This attribute is used as follows...
[CustomAuthenticationAttribute]
public class SomeDataController : Controller
{
[HttpGet]
public async Task GetData()
{
...
}
}
Now, I want to use an application service (which obtains secret private key information required for authentication from a database) and tried to use property injection for that. Injecting dependencies via the ctor is not a good choice here since it´s implemented as an attribute. So I tried...
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class CustomAuthenticationAttribute : Attribute, IAsyncAuthorizationFilter
{
public IPrivateKeyLookupService KeyService { get; set; }
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
string publicKey = ...
...
var privateKey = await this.KeyService.GetPrivateKeyFrom(publicKey);
...
}
}
...but property injection does not seem to work here. The service is registered with the IoC, but properties do not get wired. This is an ASP.NET Core 1.1 project in which I use Autofac. In the Startup class my ConfigureServices method has something like that...
public void ConfigureServices(IServicesCollection collection)
{
...
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<AuthKeyService>().As<IPrivateKeyLookupService>();
containerBuilder.Populate(services);
this.container = containerBuilder.Build();
}
Does Autofac support auto-wiring for IAsyncAuthorizationFilter types? And if not, how could I polyfill that functionality?
It turned out to be very simple...
In ASP.NET Core there is the TypeFilter attribute which is also a filter that creates another filter (specified by Type) and satisfies its constructor arguments by involving dependency injection.
I changed the implementation of IAsyncAuthorizationFilter; removed the properties and added a ctor instead, because with TypeFilter ctor injection would work now...
public sealed class CustomAuthenticationAttribute : IAsyncAuthorizationFilter
{
private readonly IPrivateKeyLookupService keyService;
public CustomAuthenticationAttribute(
IPrivateKeyLookupService keyService)
{
this.keyService = keyService;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
...
}
}
I also removed inheritance from Attribute because it´s not needed anymore as well as the declaration of the AttributeUsage attribute.
So, I can use my attribute as follows...
[TypeFilter(typeof(CustomAuthenticationAttribute))]
public class SomeDataController : Controller
{
[HttpGet]
public async Task GetData()
{
...
}
}
Passing additional arguments to the filter´s ctor is also possible via the object[] Arguments property of the TypeFilter class.
A normal thing one needs to do is get ISomething that you registered previously, especially when you implement custom attributes bet really anywhere in the HTTP pipeline will work.
Basically what you like to do is get your "hands" on a HttpContext and use the IServiceProvider located in HttpContext.RequestServices
From there it's all easy sailing if you included
using Microsoft.Extensions.DependencyInjection;
Let me demonstrate this in a small sample where I get to the registered IMemoryCache (you need to register it for this to work of course by adding services.AddMemoryCache(); in your startup.cs)
Here is the copy past stuff:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
public class SomeAttribute : Attribute,IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context )
{
IMemoryCache memory= context.HttpContext.RequestServices.GetService<IMemoryCache>();
}
}
I am trying to inject a service into my action filter but I am not getting the required service injected in the constructor. Here is what I have:
public class EnsureUserLoggedIn : ActionFilterAttribute
{
private readonly ISessionService _sessionService;
public EnsureUserLoggedIn()
{
// I was unable able to remove the default ctor
// because of compilation error while using the
// attribute in my controller
}
public EnsureUserLoggedIn(ISessionService sessionService)
{
_sessionService = sessionService;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
// Problem: _sessionService is null here
if (_sessionService.LoggedInUser == null)
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Result = new JsonResult("Unauthorized");
}
}
}
And I am decorating my controller like so:
[Route("api/issues"), EnsureUserLoggedIn]
public class IssueController : Controller
{
}
Startup.cs
services.AddScoped<ISessionService, SessionService>();
Using these articles as reference:
ASP.NET Core Action Filters
Action filters, service filters and type filters in ASP.NET 5 and MVC 6
Using the filter as a ServiceFilter
Because the filter will be used as a ServiceType, it needs to be registered with the framework IoC. If the action filters were used directly, this would not be required.
Startup.cs
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
services.AddScoped<ISessionService, SessionService>();
services.AddScoped<EnsureUserLoggedIn>();
...
}
Custom filters are added to the MVC controller method and the controller class using the ServiceFilter attribute like so:
[ServiceFilter(typeof(EnsureUserLoggedIn))]
[Route("api/issues")]
public class IssueController : Controller {
// GET: api/issues
[HttpGet]
[ServiceFilter(typeof(EnsureUserLoggedIn))]
public IEnumerable<string> Get(){...}
}
There were other examples of
Using the filter as a global filter
Using the filter with base controllers
Using the filter with an order
Take a look, give them a try and see if that resolves your issue.
Hope this helps.
Global filters
You need to implement IFilterFactory:
public class AuthorizationFilterFactory : IFilterFactory
{
public bool IsReusable => false;
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
// manually find and inject necessary dependencies.
var context = (IMyContext)serviceProvider.GetService(typeof(IMyContext));
return new AuthorizationFilter(context);
}
}
In Startup class instead of registering an actual filter you register your filter factory:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilterFactory());
});
One more way for resolving this problem. You can get your service via Context as in the following code:
public override void OnActionExecuting(ActionExecutingContext context)
{
_sessionService = context.HttpContext.RequestServices.GetService<ISessionService>();
if (_sessionService.LoggedInUser == null)
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Result = new JsonResult("Unauthorized");
}
}
Please note that you have to register this service in Startup.cs
services.AddTransient<ISessionService, SessionService>();
Example
private ILoginService _loginService;
public override void OnActionExecuting(ActionExecutingContext context)
{
_loginService = (ILoginService)context.HttpContext.RequestServices.GetService(typeof(ILoginService));
}
Hope it helps.
After reading this article ASP.NET Core - Real-World ASP.NET Core MVC Filters (Aug 2016) I implemented it like this:
In Starup.cs / ConfigureServices:
services.AddScoped<MyService>();
In MyFilterAttribute.cs:
public class MyFilterAttribute : TypeFilterAttribute
{
public MyFilterAttribute() : base(typeof (MyFilterAttributeImpl))
{
}
private class MyFilterAttributeImpl : IActionFilter
{
private readonly MyService _sv;
public MyFilterAttributeImpl(MyService sv)
{
_sv = sv;
}
public void OnActionExecuting(ActionExecutingContext context)
{
_sv.MyServiceMethod1();
}
public void OnActionExecuted(ActionExecutedContext context)
{
_sv.MyServiceMethod2();
}
}
}
In MyFooController.cs :
[MyFilter]
public IActionResult MyAction()
{
}
Edit: Passing arguments like [MyFilter("Something")] can be done using the Arguments property of the TypeFilterAttribute class: How do I add a parameter to an action filter in asp.net? (rboe's code also shows how to inject things (the same way))
While the question implicitly refers to "filters via attributes", it is still worth highlighting that adding filters "globally by type" supports DI out-of-the-box:
[For global filters added by type] any constructor dependencies will be populated by dependency injection (DI). Adding a filter by type is equivalent to filters.Add(new TypeFilterAttribute(typeof(MyFilter))).
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2#dependency-injection
With regards to attribute-based filters:
Filters that are implemented as attributes and added directly to controller classes or action methods cannot have constructor dependencies provided by dependency injection (DI). This is because attributes must have their constructor parameters supplied where they're applied. This is a limitation of how attributes work.
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2#dependency-injection
However, as mentioned in the previous answers to the OP, there are ways of indirection that can be used to achieve DI. For the sake of completeness, here are the links to the official docs:
ServiceFilterAttribute
TypeFilterAttribute
IFilterFactory implemented on your attribute
i was reading a write up on easily dependency injection in ASP.Net MVC 6 from this url http://weblogs.asp.net/scottgu/introducing-asp-net-5
they show how very easily we can inject dependency into project
1st one
namespace WebApplication1
{
public class TimeService
{
public TimeService()
{
Ticks = DateTime.Now.Ticks.ToString();
}
public String Ticks { get; set; }
}
}
register the time service as a transient service in the ConfigureServices method of the Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<TimeService>();
}
public class HomeController : Controller
{
public TimeService TimeService { get; set; }
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
public IActionResult About()
{
ViewBag.Message = TimeService.Ticks + " From Controller";
System.Threading.Thread.Sleep(1);
return View();
}
}
2nd one
public class HomeController : Controller
{
[Activate]
public TimeService TimeService { get; set; }
}
now see the second code. are they trying to say that if we use [Activate] attribute then we do not have to instantiate TimeService by controller constructor injection?
just tell me if we use [Activate] attribute then what will be the advantage ?
if we use [Activate] attribute then what line of code we can eliminate from 1st same code. thanks
The differences between the two code blocks are indeed that the first one leverages Constructor Injection to resolve the dependency on TimeService, while the second example marks a property as one that needs resolving using Property Injection.
What this means is simply that the following constructor becomes redundant:
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
As to why one would opt for Constructor versus Property Injection, I find that trying to have a list of your dependencies clearly listed out in your constructor highlights when a class becomes too dependent, which raises concerns as to what a class is trying to accomplish and, subsequently, makes it a candidate for refactoring.
Property Injection via [Activate] will not be supported from beta5 onwards.
I've run into an interesting design issue with a class library I am writing. I have a custom implementation of the AuthorizeAttribute that I want clients to be able to use like this:
[Protected("permission_name")]
In the above code, PermissionAttribute inherits from AuthorizeAttribute and uses a local default (DefaultContext created using HttpContext).
Behind the scenes, the attribute uses a SecurityService to check users, roles and permissions against (the SecurityService itself uses a client-provided persistence service that they can wire up in the composition root of their app).
So my attributes need a reference to the SecurityService to function. Since Attribute constructors can only have compile-time constants, I cannot use constructor injection.
I don't want to force my clients to use a DI framework - they should be able to discover and wire up the necessary dependencies in their composition root without using an IoC library, if they so choose.
Here are my options:
Have the library use a singleton SecurityService.
Use property injection, which would work but
it would make the dependency seem optional, which it is not and
I don't know where I can do property injection in an MVC app on an authorize attribute.
A possible solution to 2. above is to do set an instance of SecurityService as a static property on the attribute at application startup and use a guard clause to prevent it from being set more than once, like this:
class ProtectedAttribute : ...
{
private static ISecurityService _SecurityService ;
public static ISecurityService SecurityService
{
get
{
return _SecurityService ;
}
set
{
if (_SecurityService != null)
throw new InvalidOperationException("You can only set the SecurityService once per lifetime of this app.") ;
_SecurityService = value ;
}
}
}
The SecurityService could be an abstract service facade so that it can be extended/replaced by a different implementation.
Is there a better way to solve this problem?
UPDATE: Adding some code to show how I am going to do it:
Add a public property on the attribute that returns the permission name:
public class ProtectedAttribute : ...
{
private string _Permission ;
public string Permission { get { return _Permission ; } /*...*/ }
public ProtectedAttribute(string permission) { /*...*/ }
}
Setup an authorization filter and configure dependency via Ninject (if using Ninject):
using Ninject.Web.Mvc.FilterBindingSyntax;
public class MyModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
// mySecurityService instance below can have a singleton lifetime - perfect!
this.BindFilter<MyAuthorizationFilter>(FilterScope.Action, 0)
.WhenActionMethodHas<ProtectedAttribute>()
.WithConstructorArgument("securityService", mySecurityService)
.WithConstructorArgumentFromActionAttribute<ProtectedAttribute>("permission", p => p.PermissionName) ;
}
}
Ohhh it's...beautiful sniffle
With ASP.NET MVC 3 you could use constructor injection with action filters thanks to the new IFilterProvider. This way you no longer need to decorate your controller actions with action filters. You could apply them thanks to this interface and using a marker attribute.
And if you don't wanna bother implementing it manually you could always use an existing DI framework such as Ninject which provides a fluent way to define action filter dependencies.
My applications inherit from a base Application class that exposes the IOC container.
public interface IInjectableApplication
{
IUnityContainer Container { get; }
}
Then I have a base attribute class, which is aware of this
public abstract IocAwareActionFilterAttribute : ActionFilterAttribute{
protected T ResolveItem<T>(ResultExecutedContext context)
{
var app = context.HttpContext.ApplicationInstance as IInjectableApplication;
if (app == null) { throw new NullReferenceException("Application is not IInjectable."); }
T c = (T)app.Container.Resolve(typeof(T));
if (c == null) { throw new NullReferenceException(string.Format("Could not find injected {0}.", typeof(T).FullName)); }
return c;
}
}
While this is not true Injection, since Attributes aren't constructed 'normally', this provides a similar behavior. No reason it should not be adaptable to other IOCs
I have the following classes / interfaces:
public interface IProjectRepository
{
IQueryably<Project> GetProjects();
}
// Depends on my EF Context
public ProjectRepository : IProjectRepository
{
private MyDbEntities context;
public ProjectRepository(MyDbEntities context)
{
this.context = context;
}
public IQueryable<Project> GetProjects()
{
return context.Projects;
}
}
My controller:
// Depends on IProjectRepository
public class ProjectsController : Controller
{
private IProjectRepository projectRepository;
public ProjectsController(IProjectRepository projectRepository)
{
this.projectRepository = projectRepository;
}
public ActionResult Index()
{
return View(projectRepository.GetProjects());
}
}
I need to set up my dependency injection so that it passes in ProjectRepository into my Controller AND it needs to pass in my Entity Framework context into the Project Repository. I need to Entity Context to be HTTP Request scoped.
I'm not sure where I am supposed to put all the mapping code to make the dependency injection work. I also don't understand how MVC will work without the default constructor.
Can someone help me put all the pieces together? I am using StructureMap but I could easily switch to something else because I have no idea what I'm doing.
If you are using MVC 3, to do things properly, you should make use of the built in dependency resolution bits. I would highly recommend you read through the series of blog posts from Brad Wilson (member of the ASP.NET MVC team).
As far as a StructureMap specific implementation, I found the following blog posts helpful.
StructureMap and ASP.NET MVC 3 – Getting Started
StructureMap, Model Binders and Dependency Injection in ASP.NET MVC 3
StructureMap, Action Filters and Dependency Injection in ASP.NET MVC 3
StructureMap, Global Action Filters and Dependency Injection in ASP.NET MVC 3
Anyway, here's some code. To start with, I would suggest that you install the StructureMap-MVC3 NuGet package.
I can't remember what exactly it creates in the way of files, but here's what's basically involved.
/App_Start/StructuremapMvc.cs - This hooks into the Application_Start and sets up your container (SmIoC.Initialize()) and then sets the MVC 3 DependencyResolver to a your SmDependencyResolver
using System.Web.Mvc;
using YourAppNamespace.Website.IoC;
using StructureMap;
[assembly: WebActivator.PreApplicationStartMethod(typeof(YourAppNamespace.App_Start.StructuremapMvc), "Start")]
namespace YourAppNamespace.Website.App_Start {
public static class StructuremapMvc {
public static void Start() {
var container = SmIoC.Initialize();
DependencyResolver.SetResolver(new SmDependencyResolver(container));
}
}
}
/IoC/SmDependencyResolver.cs - this is your MVC 3 IDependencyResolver implementation. It's used in the App_Start code above.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using StructureMap;
namespace YourAppNamespace.Website.IoC
{
public class SmDependencyResolver : IDependencyResolver
{
private readonly IContainer _container;
public SmDependencyResolver(IContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (serviceType == null)
{
return null;
}
try
{
return _container.GetInstance(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances(serviceType).Cast<object>(); ;
}
}
}
/IoC/SmIoC.cs - this is where you setup your container... also used in the App_Start code.
namespace YourAppNamespace.Website.IoC
{
public static class SmIoC
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.For<IProjectRepository>().Use<ProjectRepository>();
//etc...
});
return ObjectFactory.Container;
}
}
}
Now everything is hooked up... (I think ;-) but you still have one last thing to do. Inside your Global.asax, we need to make sure you dispose of everything that is HttpContext scoped.
protected void Application_EndRequest()
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
So you should be able to achieve dependency injection through constructor injection, which is the correct way to go about doing things.
If you are set on using StructureMap, here is a tutorial on the setup that you will probably need.
Some other dependency injection frameworks come with custom controller factories which will do that for you. Ninject (open source dependency injection), for example has an extension that you can use that contains this behaviour. See here for example. And here to the extension.
You can use also Unity IOC which is another popular dependency injection framework with which, to my knowledge, you will have to create a custom controller factory (like with structuremap) to achieve this behaviour. See here for an example.
You can also research all other dependency injection frameworks to see what support you can get with each.
EDIT:
I hope I am explaining this correctly but here is some background info.
MVC uses a controller factory that has the responsibilities of instantiating the respective controllers needed when a request is made. By default, it will initialize a controller by calling its parameterless constructor.
To create the infrastructure for the constructor parameter injection you need to create a custom factory that can resolve constructor parameters. That is where the dependency injection containers come in: essentially the DI container (if configured properly) knows how to resolve those dependency and your custom factory will leverage it to request the registered dependencies and pass the to the controller constructor.
All work pretty much the same. Historically, all have had setter injectors (set up a property that is then filled), but most have constructor injection now. In structure map, the easiest way to accomplish this is use the attribute: [StructureMap.DefaultConstructor].
Once you add the attribute, the objects you have placed in your "map" should inject without any extra work. If you can't use attributes, consider using the setter.
There is a file on the structure map site:
http://structuremap.net/structuremap/ConstructorAndSetterInjection.htm
When using StructureMap I would generally have something like this in my controller:
private static IProjectRepository GetProjectRepository()
{
var retVal = ObjectFactory.TryGetInstance<IProjectRepository>()
?? new ProjectRepository();
return retVal;
}
If the TryGetInstance returns null (because nothing was set for that type) it will default to the concrete type you specify.
Now you have a bootstrapper somewhere like this:
public static class StructureMapBootStrapper
{
public static void InitializeStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IProjectRepository>().Use<ProjectRepository>();
}
}
}
Now you call this bootstrapper in your Global.asax Application_Start event:
protected void Application_Start()
{
StructureMapBootStrapper.InitializeStructureMap();
}
Now in a test project, when you want to inject a mock repository you can just do this:
[TestMethod]
public void SomeControllerTest()
{
StructureMap.ObjectFactory.Inject(
typeof(IProjectRepository),
new MockProjectRepository());
// ... do some test of your controller with the mock
}