MVC Controller - Inject 2 repositories in controller - asp.net-mvc-3

I'm trying to inject a second repository into my asp.net mvc 3 controller. And I cant get it to work, not sure where to "add another" using Ninject.
I have a void function in global.asa.cs
kernel.Bind<INewsRepository>().To<NewsRepository>();
And in my controller I have:
private INewsRepository _newsRepository;
private IContentRepository _contentRepository;
public NewsController(INewsRepository newsRepository, IContentRepository contentRepository)
{
this._newsRepository = newsRepository;
this._contentRepository = contentRepository;
}
How can I register IContentRepository for the NewsController as well?

I use autofac instead of Ninject but the basics stay the same.
If you got your first dependency injection working then you should be able to bind others as well. You just have to add a new binding in Application_Start() in your Global.asax.
So under your first binding do this as well:
kernel.Bind<IContentRepository>().To<ContentRepository>();
You can have as many bindings as you like.

First off it's a good practice to move the bootstrapping of your application into a separate location. This keeps your Global.asax clean.
You should also be using convention based registration. It will end up saving you lots of time for the bindings you don't need to customize.
So for you I'd probably suggest the following
public static class Bootstrapper()
{
public static void Bootstrap()
{
kernel.Scan( k =>
{
k.FromAssemblyContaining<INewsRepository>();
k.BindWithDefaultConventions();
});
}
}
And in your Global.asax you add this..
Bootstrapper.Bootstrap();
Then I would suggest you spend some time on Google reading about ninject conventions.

Related

ninject 3 render out object context instances

Entity Framework 4, Ninject 3, MVC3
Currently in my web app i have been using a rather rudimentary approach to per request instantiation of an Object Context. So I am experimenting with Ninject, and some old sample code, but I am unsure how to proceed with the following..
Effectively I want to be able in the controller to do the equivalent of: DB_Entities.Current.Albums ... Should i be instantiating a StandardKernel every time?
The sample i was looking at was using the following: MvcApplication.Container.Get(); but in Ninject 3 with the App_Start hookup I dont have access to Container..
My attempt to replicate the above line, is failing at runtime.
using MusicStoreEntities;
using Ninject;
using TestMVC3WithIOC.App_Start;
using System.Data.Objects;
namespace TestMVC3WithIOC.Models
{
public partial class MusicStoreEntities
{
public static MusicStoreEntities Current
{
get
{
using (IKernel kernel = new StandardKernel())
{
return (MusicStoreEntities)kernel.Get<ObjectContext>();
}
}
}
}
}
Also, note, that in App_Start\NinjectWebCommon.cs I have the following modification:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ILogger>().To<NLogger>();
kernel.Bind<ObjectContext>().To<MusicStoreEntities>().InRequestScope();
}
Although a workable solution, it seems ill-advised to pass the entire Kernel into a class, because it tends to obscure the classes actual, specific dependencies. A better approach is to pass a factory dependency into your controller's constructor.
public partial class MusicStoreEntities
{
private readonly IEntitiesFactory _factory;
public MusicStoreEntities(IEntitiesFactory factory)
{
_factory = factory;
}
}
IEntitiesFactory has a simple implementation with a single method GetObjectContext().
(I believe also the "Unit of Work" pattern is popular at the moment, but I can't really speak to that as I haven't used it. Maybe worth looking into.)

How to run a method at the beginning of an MVC3 project?

I need to populate an element from the Database, first thing when I compile/run my MVC3 application.
I have a static class and static method to populate the element. I just need to know how I could somehow call the method at the startup of my application.
Here's the code:
public static class Select_Brands
{
public static IQueryable<Brand> BrandsQ { get; set; }
public static IQueryable<Brand> GetBrands()
{
using (Online_Store_DBEntities EFModel = new Online_Store_DBEntities())
{
BrandsQ = EFModel.Brands;
}
return BrandsQ;
}
}
Is there any way ?
In every MVC Application you have a Global.asax like in an ASP.NET Application and you can run code in Application_Start() Method.
But you should think about where to persist the data and what you really use this for.
There is a method in the global.asax file called Application_Start - sounds like this could be a candidate for what you want.

Plugin Architecture with ninject – load class and controller instances from plugin assembly to main MVC project

I use this tutorial to create Plugin Architecture in my solution and I also use ninject for the first time:
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=358360&av=526320&msg=4308834#xx4308834xx
Now in MVC application while user is in the process of checkout I get the payment method he selects and need to retrieve the plugin for the selected payment method. I have succeeded in retrieving plugin controller this way, though I have no idea whether it is safe or acceptable practice:
Type type = Type.GetType(paymentMethod.PaymentMethodPluginType);
//get plugin controller
var paymentController = ServiceLocator.Current.GetInstance(type) as BasePaymentController;
//get validations from plugin
var warnings = paymentController.ValidatePaymentForm(form);
//get payment info from plugin
var paymentInfo = paymentController.GetPaymentInfo(form);
//…
I also need to access a plugin class for processing the payment.
I have an interface IPaymentMethod
public partial interface IPaymentMethod
{
void PostProcessPayment (PostProcessPaymentRequest postprocessPaymentRequest);
}
And plugin PaymentProcessor like this
public class PluginPaymentProcessor :IPaymentMethod
{
public void PostProcessPayment (PostProcessPaymentRequest postprocessPaymentRequest)
{
///
}
Now in MVC project I try to access PostProcessPayment method this way
IPaymentMethod pluginpaymentmethod = ServiceLocator.Current.GetInstance<IPaymentMethod>(paymentMethod.PaymentProcessor);
here paymentMethod.PaymentProcessor is “MyApp.Plugins.MyPlugin.PluginPaymentProcessor, MyApp.Plugins.MyPlugin,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”
And want to use pluginpaymentmethod like i do in controller example
pluginpaymentmethod.PostProcessPayment(postProcessPaymentRequest);
but it throws error that resource is not found and pluginpaymentmethod is not loaded. How can I fix it or can you suggest any tutorial with similar implementations? Thank you.
assuming you have a concrete class called MyPlugin which has the IPaymentMethod interface, then your ninject bindings should look a bit like:
private static void RegisterServices(IKernel kernel){
kernel.Bind<IPaymentMethod>().To<MyPlugin>().InRequestScope();
}
check that this is in place in your NinjectWebCommon.cs class under the App_Start folder. A trickier scenario might be that IPaymentMethod has to be registered in the same way that the Ninject IKernel is bound:
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
that would potentially be a trickier issue to work out.

ASP.Net MVC 3 - instantiate data context class in BaseController

When adding a controller in ASP.Net MVC 3 using "Controller with Read/Write actions and views, using EntityFramework" as template, it generates a class as follows:
namespace Project.Controllers
{
public class Default1Controller : Controller
{
private ProjectEntities db = new ProjectEntities();
...
}
}
Now, I would like to know if it would be a good practice to change this so that my Controller would inherit a custom base controller that would instantiate ProjectEntities. It would look as follows:
BaseController:
namespace MatchesHorsConcours.Controllers
{
public class BaseController : Controller
{
protected MatchesEntities db = new MatchesEntities();
...
}
}
Other controllers:
namespace Project.Controllers
{
public class Default1Controller : BaseController
{
...
}
}
This technique is useful when you need logic in your master page (for example, to dynamically render menu options). Read about this here: http://www.asp.net/mvc/tutorials/passing-data-to-view-master-pages-cs
However, in general this is not a good technique. I would recommend using dependency injection (Ninject works well with MVC and is easy to implement)
No absolutely not. It makes totally untestable. Please use repository pattern and constructor injection if possible: Repository Pattern vs DAL

Getting SNAP(AOP), NInject and ASP.Net MVC 3 working together

Has anyone got the SNAP AOP framework working with MVC 3 and Ninject.
The samples given when adding Snap using NuGet to an MVC 3 project don't specifcally work well with a previously added NInject package. I have tried to get it working based on the normal NInject approach but just cannot get it to actually intercept!
Can anyone show how to do this in code please?
I figured it out with the latest version of Ninject through NuGet which now adds a class call NinjectMVC3 in a new AppStart folder in the MVC3 application.
The code I used is as folows:
In the automatically created NinjectMVC3.cs CreateKernel() method:-
private static IKernel CreateKernel()
{
// Wire it up with AOP
NinjectAopConfiguration.NinjectAopConfigure();
//var kernel = new StandardKernel(); // Removed
RegisterServices(NinjectAopConfiguration._container.Kernel);
return NinjectAopConfiguration._container.Kernel;
}
I also wired up Ninject for the various injection targets in RegisterServices() method.
Next I took the sample code generated by NuGet when adding SNAP.Ninject to the MVC 3 application, renamed it NinjectAOP.cs and made it look like this:
public static class NinjectAopConfiguration
{
public readonly static NinjectAspectContainer _container;
static NinjectAopConfiguration()
{
_container = new NinjectAspectContainer();
}
public static void NinjectAopConfigure()
{
SnapConfiguration.For(_container).Configure(c =>
{
c.IncludeNamespace("MyNamespace.Model.*");
c.Bind<ExceptionLoggingInterceptor>().To<ExceptionLoggingAttribute>();
});
}
}
I also needed to do an assembly binding redirect for Ninject as follows because there is an assembly version conflict somewhere for Ninject:
I hope this helps someone.
I invite anyone to have a look and see if they can improve this please.

Resources