I have a problem that I don't know how to solve. I have a container which contains different interfaces for different services that I expose with a WebApi. The problem is that I need to get that dependencies inside my controller and I must avoid the use of static. I read about this
http://beletsky.net/2011/10/inside-aspnet-mvc-idependencyresolver.html
http://www.asp.net/web-api/overview/advanced/dependency-injection
In the asp.net I read that I can implement my own IDependencyResolver. Is this madness? because I searched a lot and I only found examples using Unity. If I don't want to use that dependency injector? What it's the best way to achieve this?.
public class MyController: ApiController
{
private InterfaceService m_interfaceService; //This is the dependency I need
public MyController()
{
}
[HttpGet]
[Route("myServices/")]
public List<IServiceCategory> GetServiceObjectsList()
{
return m_interfaceServices.GetObjectsList();
}
}
So you have an pre-existing container/dependency mechanism! You should ask your team why it was a good idea to make something like that instead of using all the good ones out in the .net world.
Nonetheless, from the docs:
http://www.asp.net/web-api/overview/advanced/dependency-injection
Although you could write a complete IDependencyResolver implementation
from scratch, the interface is really designed to act as bridge
between Web API and existing IoC containers.
The Unity example on that page shows what must be done to bridge the gap between Unity DI framework and the web mvc. You just need to do the same thing with your home-rolled one. It's matter of implementing just a few methods. Go for it!
Here is an implementation that meets your requirements:
namespace AdvancedDI.Controllers
{
public class ProductController : ApiController
{
public IFactory iFactory { get; set; }
protected override void Initialize(HttpControllerContext controllerContext)
{
DIAPP.GetContainer(this);
base.Initialize(controllerContext);
}
public IHttpActionResult Get()
{
var response = iFactory.DoWork();
return Ok(response);
}
protected override void Dispose(bool disposing)
{
DIAPP.Dispose(this);
base.Dispose(disposing);
}
}
}
This is one kind of property based injection. It is possible with UnityContainerExtensions. The Initialize method will get called before Get.
Step 1. DIAPP.GetContainer(this) carries the entire productController context.
Step 2. GetContainer receives the IFactory property information from this.
Step 3. Next, you have a chance to receive the unity IBuilderContext for this IFactory.
I've used both Ninject and AutoFac for dependency injection. This is not madness, it's common practice.
Related
I have a Xamarin forms app that is using dryioc for IoC. It seems all my services get disposed as soon as the view is out of scope
This is how I am registering the service in the app.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IInboxService, InboxService>();;
}
and I resolve it this way in the app.cs
protected override void OnInitialized()
{
_started = DateTime.Now;
InitializeComponent();
InitializeAppSettings();
Container.Resolve<ISyncService>().Init(new List<ISyncableService>
{
Container.Resolve<IInboxService>()
});
}
When I need to use it in a viewmodel I put it in the constructor like so.
public class HomeViewModel {
public HomeViewModel(InboxService inboxService)
{
}
}
The singleton is respected but then it will dispose and create a new one when it needs it. Anyone else run into this ?
Xamarin Version: 5.0.0.2125
Prism Version: 8.1.97
LocIOS Version: 8.1.97
public HomeViewModel(InboxService inboxService)
This injects a concrete InboxService instance, which is independent of the registration of interfaces that it might implement. If you want your singleton, request an IInboxService:
public HomeViewModel(IInboxService inboxService)
I try to give a service implementing a certain interface a meaningful name that's more than just interface's name minus I, like DummyInboxService, TestInboxService, ImapInboxService, Pop3InboxService, RemoteInboxService... thus making clearer what the respective implementation actually does and helping finding these errors (most likely a typo anyway) early.
I've created two projects:
Web Project, that contains all the viewmodels/data/controllers etc. And a Web Api project to allow form capture.
I simply want to capture the data in the web Api and save it to the database where it will become accessible to the front end.
I am experiencing an issue initialzing the DBcontext within the Api controller and need help.
namespace ZebraCRM.API2.Controllers
{
[Route("api/[controller]")]
public class LeadsController : Controller
{
private readonly ApplicationDbContext _context;
public LeadController(ApplicationDbContext context)
{
_context = context;
}
// POST api/values
[HttpPost]
public void Post(Lead formData)
{
formData.DateCreated = DateTime.Now;
_context.Lead.Add(formData);
_context.SaveChanges();
}
}
The above idea was taken from the controller in the main web project, but is obviously not the right approach in this situation.
the debug outputs the following
System.InvalidOperationException: Unable to resolve service for type 'ZebraCRM.Web.Data.ApplicationDbContext' while attempting to activate 'ZebraCRM.API2.Controllers.LeadsController'.
The framework doesn't know how to constructor a LeadController because it doesn't know how to satisfy the ApplicationDbContext context parameter when it calls the constructor. To solve this, you could simply assign the value as part of your constructor, eliminating the parameter.
namespace ZebraCRM.API2.Controllers
{
[Route("api/[controller]")]
public class LeadsController : Controller
{
private readonly ApplicationDbContext _context;
public LeadController()
{
_context = new ApplicationDbContext();
}
// POST api/values
[HttpPost]
public void Post(Lead formData)
{
formData.DateCreated = DateTime.Now;
_context.Lead.Add(formData);
_context.SaveChanges();
}
}
}
Or, if you do want to leave the constructor parameter in place, you'll need a DI container such as AutoFac or Ninject. If you're new to DI, I suggest you watch this video. When you set things up for Dependency Injection, you will basically pass something to the framework that says "When constructing an object that needs an X, here's how you give it an X". This allows you to better follow SOLID principles. An object can demand an IRepository (an interface) and as part of your DI setup you can say "when an object demands an IRepository, I want to pass it a SqlServerRepository (which would implement IRepository)". Then if you later decided to switch to MySQL, you could modify the setup to use a MySqlRepository instead of SqlServerRepository, without needing to modify anything about the controller, since the controller would use the repository via the interface.
As I am learning about Dependency Injection, so I have also shared my understanding (Please correct me wherever you guys feel to do so). The concept behind the following sample is to check the advantage of using Dependency Injection as it helps in implementing loose coupling in the application which will further prevent me from making lots of changes in the project in the case when concrete definitions (classes) tend to change in future.
IEmailService - Interface:
public interface IEmailService
{
void SendMail();
}
EmailService - Class inheriting above interface
public class EmailService : IEmailService
{
public EmailService(string emailFrom, string emailTo)
{
}
public void SendMail()
{
// Code here
}
}
HomeController
public class HomeController : Controller
{
private IEmailService _service;
public HomeController(IEmailService service)
{
_service = service;
}
public IActionResult Index()
{
_service.SendMail();
return View();
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
...
services.AddTransient<IEmailService, EmailService>();
...
}
Practical assumption
I assume that earlier there was no parameterized constructor in the EmailService class, but in future, I feel like I need to add a parameterized constructor but it shouldn't have an impact on those controllers (like HomeController) which are using abstraction (interfaces) to access them indirectly.
Unfortunately, when I am running the above code, I am getting the following exception which seems to disappear if I am removing the parameterized constructor from EmailService class.
InvalidOperationException: Unable to resolve service for type 'System.String' while attempting to activate 'DependencyInjectionDemo.Services.EmailService'.
You can register your EmailService using a lambda:
services.AddTransient<IEmailService>(_ => new EmailService("from#", "to#"));
emailFrom and emailTo however seem runtime data, which means that the Controller might be responsible of supplying this information to the IEmailService. Since the EmailService is decoupled from the controller, it means that the controller is not responsible of its creation.
In general, you should prevent needing to initialize your components (EmailService in your case) with runtime data, as explained here, the advice is:
Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. My advice is to let runtime data flow through the method calls of constructed object graphs.
In your case this basically means changing the IEmailService abstraction to the following:
public interface IEmailService
{
void SendMail(string emailFrom, string emailTo);
}
Adding Structuremap MVC 5 to an ASP.NET MVC project. I would like to have a singleton of my database connection per request - my controllers would share the same database connection. I am implementing the repository pattern here and need each controller to have a copy of its respective repository. I know this is possible but I think I'm missing or mis-interpretting something wrong.
I have a controller, "Bag," that needs a "IBagRepo"
public class BagController : Controller
{
private readonly IBagRepo repo;
public BagController(IBagRepo repo)
{
this.repo = repo;
}
// actions
}
My first attempt was hooking the singleton database connection in the ControllerConvention, as I assume its called once
public class ControllerConvention : IRegistrationConvention {
public void Process(Type type, Registry registry) {
if (type.CanBeCastTo<Controller>() && !type.IsAbstract) {
// Tried something like
registry.For(type).Singleton().Is(new ApplicationDbContext()); // this
registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
}
}
}
But it came clear that this isn't the right file to make this change. I went into the registry class that was automatically generated upon installing the nuget package and tried fiddling around with this.
public class DefaultRegistry : Registry {
#region Constructors and Destructors
public DefaultRegistry() {
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
// httpContext is null if I use the line below
// For<IBagRepo>().Use<BagRepo>().Ctor<ApplicationDbContext>().Is(new ApplicationDbContext());
}
#endregion
}
I haven't seen a problem like this out here yet. Am I passing in the right types within my DefaultRegistry class?
What you're wanting is effectively the default behavior if you had been using the StructureMap.MVC5 nuget: https://www.nuget.org/packages/StructureMap.MVC5/. As long as your DbContext is registered with the default lifecycle, that package is using a nested container per http request which effectively scopes a DbContext to an HTTP request for unit of work scoping.
Different tooling than MVC & EF, but I described similar mechanics for FubuMVC + RavenDb w/ StructureMap in this blog post: http://jeremydmiller.com/2014/11/03/transaction-scoping-in-fubumvc-with-ravendb-and-structuremap/
I ended overriding the default controller factory and not using structuremap
I want to add per session lifestyle for one of my controllers in an ASP.NET MVC app but it currently has no such option. I've searched the stackoverflow and found the next solution
public class PerSessionLifestyleManager : AbstractLifestyleManager
{
private readonly string PerSessionObjectID = "PerSessionLifestyleManager_" + Guid.NewGuid().ToString();
public override object Resolve(CreationContext context)
{
if (HttpContext.Current.Session[PerSessionObjectID] == null)
{
// Create the actual object
HttpContext.Current.Session[PerSessionObjectID] = base.Resolve(context);
}
return HttpContext.Current.Session[PerSessionObjectID];
}
public override void Dispose()
{
}
}
But I want to be able to write somethink like
cr => cr.LifeStyle.PerSession.Named(cr.Implementation.Name)
I use Castle Windsor 3.0 and found that LifestyleType enum is contained inside Castle.Core namespace, it is being used by the DefaultKernel. My suggestion is to override the DefaultKernel but I do not really know how to do it bug free and seemlessly as if PerSession lifestyle if shipped with the dll.
So there are two things that you're asking about.
First is how to implement the lifestyle. Good starting point would be to look at how per-web-request lifestyle is implemented (use Scoped lifestyle with custom scope and scope accessor)
Second, how to surface that in the API. what I recommend is to have an extension method that encapsulates your lower level call to LifestyleScoped<YourCustomScopeAccessor>() with LifestylePerSession() similar to how WCF Facility does it.