structuremap asp .net mvc registration - asp.net-mvc

I'm using structuremap and Asp .Net MVC in a project. Currently I'm registering my dependency resolutions in the MVC layer for everything below it (service, data, etc.). However, I was wondering how I could do this by only registering what's directly below the MVC layer, namely, the Service layer. Basically my controllers have services injected into them and that's all I want my UI layer to know about. Within the service classes I have repositories injected and want those registered with structuremap in there... and so on. In other words, I want each layer to only be dependent (as much as possible) to the layer directly below it.
Thanks!

A good approach is to use structuremap conventions combined with structuremap registries. That will take care of most of your registration issues. Structuremap can scan your bin and map dependencies that it finds in all dll's in your bin.
Look into the Scan method combined with a StructureMap Registry class:
Scan(x =>
{
x.AssembliesFromApplicationBaseDirectory(y =>
y.FullName.StartsWith("JustLookAtTheseDlls"));
// Use default conventions
x.WithDefaultConventions().OnAddedPluginTypes(y =>
y.HybridHttpOrThreadLocalScoped());
//Are there any registries? If so, register them
x.LookForRegistries();
}
A registry looks something like this, and you can just drop one into each of your projects to register the items in each:
public class IocRegistry :
StructureMap.Configuration.DSL.Registry
{
public IocRegistry()
{
For<IDocumentStore>().Singleton()
.Use<RavenStore>();
}
}
You root application should have the registry that contains the scan statement above. Then initialize structuremap like so:
ObjectFactory.Configure(x => x.AddRegistry(
new MyTopLevelRegistry()));
Where MyTopLevelRegistry looks like this:
public class MyTopLevelRegistry: Registry
{
public MyTopLevelRegistry()
{
Scan(x =>
{
x.AssembliesFromApplicationBaseDirectory(
y => y.FullName
.StartsWith("InsertYourNamespacePrefix"));
x.WithDefaultConventions().OnAddedPluginTypes(
y => y.HybridHttpOrThreadLocalScoped());
x.LookForRegistries();
});
}
}
Keep in mind if you set it to "WithDefaultConventions" it will automatically map IMyClass to MyClass so you don't even have to specify that stuff in the registries. You just have to register items that don't follow that convention.
Hope this helps!

I recommend the usage of a composition root in a own library.
In the project i am working on we put the StructureMap registry in a library named xx.yy.IoC and we call the configuration code from Global.asax.
The MVC layer has only a link to the IoC library. The IoC Library has the dependencies to the other layers (Domain, Data, etc.)
As a tip: This article has changed our views about layering. jeffrey palermo onion architecture

I'm not sure I understand what you are asking.
You have to register all the objects that will be resolved. Then in your controller you just expect ISomeService passed to constructor. Controller doesn't know that ISomeService has injected IRepositories for example.

Related

asp.net 5 dependency injection in multiple projects

I've got an ASP.NET 5 dnxcore solution with some projects to separate my logic:
API
Core (with services for business logic)
DAL (repository interfaces)
Entity Framework (the repositories implementations)
Now I use DI to call my services in the constructors of my API controllers:
private readonly IMyService _myService;
public Controller(IMyService myservice){ _myService = myService; }
The services in my core get the repository thru constructor injection too:
private readonly IMyRepository _myRepo;
public MyService(IMyRepository myRepo){ _myRepo = myRepo; }
Currently I need to define my DI container in the startup class of my API to make it work.
My question is, how can I put the 'building' of the DI container of the repositories in my services in my Core-project. This way, my API is loosely coupled of the fact that my services use Entity Framework, so I can change to, for example, mongodb without changing my API project.
My question is, how can I put the 'building' of the DI container of the repositories in my services in my Core-project. This way, my API is loosely coupled of the fact that my services use Entity Framework, so I can change to, for example, mongodb without changing my API project.
You could, but you shouldn't do that.
Dependency Injection is the practice of making loosely-coupled classes throughout the libraries that can be plugged together (often in many ways).
However, each application should have a composition root, which is the one place in the application where we put the coupling code. Our first instinct as developers is to try to farm the coupling code off into its own library, but that is an urge that you should resist. See composition root reuse.
Mark Seeman's illustration sums it up well. Avoiding transitive dependencies is what is desired when using DI in order to flatten the dependency graph. This ensures assemblies can be used/tested in isolation without dragging along unnecessary dependencies, which in turn makes maintenance easier.
That said, many DI containers have a way to organize the configuration of certain parts of the application by using modules. In Autofac, the documentation for modules is here.
You can easily add an extension method of IServiceCollection into your services layer and use it to register its own dependencies.
Then in the startup you just call the method on the service layer without having any reference to EntityFramework in your web app.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace your.service.layer
{
public static class MyServiceCollectionExtensions
{
public static IServiceCollection AddMyServiceDependencies(this IServiceCollection services)
{
services.AddScoped<My.Data.Tier.DbContext, My.Data.Tier.DbContext>();
}
}
}
Startup:
using your.service.layer;
public void ConfigureServices(IServiceCollection services)
{
services.AddMyServiceDependencies();
}
Now your web app only needs a reference to your service layer and it is not directly dependent on EntityFramework.
As NightOwl888 have said, you should have a CompositionRoot in your application, the place where all your dependencies are set.
What I did is this:
1. Create a Core Class Library named CompositionRoot.
2. Add a class to handle your dependencies:
public class DependencyMapper
{
public static void SetDependencies(IServiceCollection serviceCollection, IConfigurationRoot configuration)
{
serviceCollection.AddEntityFramework()
.AddDbContext<SonoPeopleContext>(options =>
options.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"])
);
MapperConfiguration mapperConfiguration = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfileConfiguration());
});
serviceCollection.AddSingleton<IMapper>(sp => mapperConfiguration.CreateMapper());
serviceCollection.AddScoped<IUserService, UserService>();
}
}
Then you reference your CompositionRoot in your MVC project and in your Startup.cs you just do
DependencyMapper.SetDependencies(services, Configuration);
That's all.
See this question, I have the same problem because my application is DB agnostic and base on the request will need to switch between a document oriented database (noSQL) and transaccional database (SQL).

Translating Ninject to ASP.NET MVC 6 DI

I am trying to get into the new ASP.NET MVC 6 stuff, but I'm having a very hard time with their new DI system. I have tried to find resources online, but everything I find covers only the absolute most bare minimum to use it.
I was previously using Ninject, and I have several wire-ups that work like this:
Bind<IDocumentStore>()
.ToMethod(c => CreateDocumentStore())
.InSingletonScope();
private static IDocumentStore CreateDocumentStore() {
// lots of initialization code, etc.
return documentStore;
}
But so far I am having a difficult time finding out how to translate this kind of behaviour to Microsoft's new DI system. All I can find are examples like this:
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
and:
services.AddMvc();
Where everything seems to work entirely on the default constructor for the target service. Is there any way to produce the behaviour I am needing in this new DI system?
I've seen the
services.Configure<TOptions>(options => {});
But I'm not really clear on whether that will do what I am thinking, or if it is reserved for specific behaviours.
The AddTransient method has various overloads, one of which accepts a lambda expression:
services.AddTransient<IDocumentStore>(s => CreateDocumentStore());
However it seems you are using the Ninject InSingletonScope() modifier so this may be more appropriate:
services.AddSingleton<IEmailSender>(s => CreateDocumentStore());
Additional note: There is some pre-release documentation available (of course, it's not complete and may be incorrect but may help)
Also you could continue use Ninject by adding Microsoft.Framework.DependencyInjection.Ninject to your project and then configure it with following code:
public IServiceProvider ConfigureServices(Microsoft.Framework.DependencyInjection.IServiceCollection services)
{
var kernel = CreateMyKernel();
kernel.Populate(services); // Wire up configured services and Ninject kernel with Microsoft tool
return kernel.Get<IServiceProvider>();
}

Two MVC applications using ninject to the same services and repositories

I am setting up a n tier system and have chosen to use ninject as the IoC/Di container. As part of this application I have got two MVC front ends. One is for the end user and the other is for the Administraion and configuration. I have chose two fron ends so that views & controllers e.t.c are contained and will make thinks a little easier to manage when I get to 100+ containers.
Anyway... What I want to know is?
Can I make my startup project the Admin application and instanciate Ninject e.t.c from here then when my second MVC application is called by the user it can use the same Ninject container which has alread been instantiated?
I hope this make sense to you all.
Also as an aside, does anyone know how to use Ninject to inject the DBcontext connection string/name?
You could create separate class library (called maybe SharedConfiguration?) with class
public static class NinjectSharedConfiguration
{
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<MyDbContext()
.ToSelf()
.InRequestScope()
.WithConstructorArgument("nameOrConnectionString", "server = .;");
}
}
And make call to this method from both projects

For specific controller make Windsor instantiate different classes

I use S#arp Architecture which uses Windsor Castle for IoC. I got a new controller now that, unlike all other controllers in the project, need a different implementation of the same interfaces. I.e. all controllers use ProductsRepository: IProductsRepository as implementation, but the new one has to use SpecificProductsRepository.
How do I configure it to recognize and manage this automatically? Either in pure Windsor way, or with ASP.NET MVC help (e.g. in my custom controllers factory).
OK looks like I need subcontainers. Still searching.
An easier and much simpler way would be to use Windsor's service overrides.
E.g. register your repos like so:
container.Register(Component.For<IProductsRepository>
.ImplementedBy<ProductsRepository>()
.Named("defaultProductsRepository"),
Component.For<IProductsRepository>
.ImplementedBy<SpecificProductsRepository>()
.Named("specificProductsRepository"));
which will ensure that the default implementation is ProductsRepository. Now, for your specific controller, add a service override like so:
container.Register(Component.For<NewController>()
.ServiceOverrides(ServiceOverride
.ForKey("productsRepository")
.Eq("specificProductsRepository"));
You can read the docs here.
Edit: If you want to register your repositories with AllTypes, you can adjust the registration key e.g. like so:
container.Register(AllTypes.[how you used to].Configure(c => c.Named(GetKey(c)));
where GetKey e.g. could be something like:
public string GetKey(ComponentRegistration registration)
{
return registration.Implementation.Name;
}
OK, these days I tend to answer my own questions... so here it is for those who need it.
// create subcontainer with specific implementation
var mycontainer = new WindsorContainer();
mycontainer.Register(AllTypes.Pick()
.FromAssemblyNamed("My.Data")
.WithService.FirstInterface()
.Where(x => x.Namespace == "My.Data.Custom")
.Configure(x => x.LifeStyle.Is(LifestyleType.PerWebRequest)));
container.AddChildContainer(mycontainer);
ControllerBuilder.Current.SetControllerFactory(new ExtendedControllerFactory(
new Dictionary<string, IWindsorContainer> { {"", container}, {"Lm", mycontainer} }));
The controller factory chooses appropriate container based on name. The biggest challenge there is to call appropriate container's Release(controller) at the end of request, i.e. remember which container was used to instantiate controller. But this can be solved in several ways I suppose - remember in thread-specific (in HttpContext), remember in BaseController property, remember in internal dictionary, etc.

Architecting medium size asp mvc - using ninject and creating objects

I'm designing medium-size website using asp.net mvc technology.
All business logic is organized into IServices (like IDomainService, IUserService, IAuthService, ITrainingService). All services are using IRepositories.
I'm using Ninject 1.5 to wire services with controllers and it seems working perfectly.
There is so far one subject I have no idea how to handle. Some services create contexts (per request) - for instance IDomainService creates DomainContext (per request) which is needed for IUserService.
ITrainingService is used only in TrainingController, which is accessible only by authorized users, and ITrainingService requires UserContext (also per request) to know who is having training.
This is my first project using IoC container.
Is there any design pattern or code-schema how to solve it?
I think I can fill context object using ActionFilters but how to manage their lifetime and where to put them to be accessible for IServices? (in an ellegant way)
I've used Ninject specifically in an MVC application. The way you'd accomplish this with Ninject is in the configuration or binding of your dependencies. When you do this, you specify how you want your object lifetimes to be managed. In most cases of a web app, you objects will be per request as you've indicated in your question.
One thing I've noticed in your question is that your DomainContext is being created by an IDomainService object and is used by other objects. If the domain service object is a sort of factory for a DomainContext, then you don't have much of a problem -- this becomes an exercise of how you configure Ninject to provide concrete objects and inject dependencies.
Here's general guidance on how you would structure your application -- bear in mind I don't have full understanding of your interfaces and classes:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Note above that the easiest way to get Ninject to work is to derive your application class from the NinjectHttpApplication class. You will need to change your RegisterRoutes to an override method and will also be required to implement a method called CreateKernel. The CreateKernel method is responsible for returning the Ninject kernel which is itself the IoC container.
In the CreateKernel method, the Ninject-provided AutoControllerModule scans assemblies for MVC controller classes and registers them with the container. What this means is that dependencies on those controllers can now be injected by Ninject as it has become the controller provider for the application. The ServiceModule class is one that you need to create to register all of your services with Ninject. I'm guessing it would look something like this:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Ninject's got a pretty expressive fluent interface for configuration. Note above that each statement basically associates a concrete class with an interface it implements. The "Using" phrase in the statement indicates to the Ninject kernel that the object will live for the life of the request only. So, for example, this means that anytime an IDomainService object is requested from the Ninject kernel during the same request, the same object will be returned.
As for you context objects, I'm taking a stab that your domain service creates these contexts and acts as a factory of sorts. In that regard, I bound instances DomainContext classes above to be produced by getting the value of the a property called CurrentDomainContext off the IDomainService. That's what the lambda above accomplishes. The nice thing about the "ToMethod" binding in Ninject is that you have access to a Ninject activation context object that allows you to resolve objects using the kernel. That's exactly what we do in order to get the current domain context.
The next steps are to ensure your objects accept dependencies properly. For example, you say that ITrainingService is used only in the TrainingController class. So, in that case I would ensure that TrainingController has a constructor that accepts an ITrainingService parameter. In that constructor, you can save the reference to the ITrainingService in a member variable. As in:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Remember that Ninject has already registered all of your controllers with the Ninject kernel, so when this controller is created and it's actions are invoked, you'll have a reference to the ITrainingService by way of the trainingService member variable.
Hope this helps you out. Using IoC containers can become quite confusing at times. Note, I highly recommend you check out the Ninject documentation -- it's a very well written introduction to Ninject as well as DI/IoC concepts. I've also left out discussion of the AutoWiringModule shown above; however, Nate Kohari (Ninject's creator) has a good write-up on his blog about this feature.
Good luck!
Im not exactly sure if I understand your problem completely, hopefully this bit of advice can help.
When using an IoC container you let the container handle object lifetime managment. I have only used Castle Windsor and StructureMap for dependency injection so I cant give you a concrete example for how to do this with Ninject.
Looking through the Ninject documentation I think you want to look at Activation Behaviours to specify object lifetime management.
Hope this helps.

Resources