I have a property in my web api self hosted app that I would like to inject to my controllers, which is loaded via reflection using my custom IoC framework, here is my startup code:
public CustomClass StuffInstance { get; set; }
// This method is required by Katana:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var webApiConfiguration = ConfigureWebApi();
// Use the extension method provided by the WebApi.Owin library:
app.UseWebApi(webApiConfiguration);
}
my controllers are mostly scaffolded and some like:
// PUT: api/EventTypeDescriptions/5
[ResponseType(typeof(void))]
public IHttpActionResult PutStuff(int id, int something)
{
//do stuff
//here i would like to use StuffInstance like a singleton
return StatusCode(HttpStatusCode.NoContent);
}
how can a inject StuffInstance to my controllers? this information would be relevant to anyone making an IoC framework btw
I found the information to inject instances to my controllers in this link:
http://www.asp.net/web-api/overview/advanced/dependency-injection
basically i implemented a dependency resolver for my custom IoC Library
in case someone has the same problem, here is the code, maybe for other IoC frameworks it needs more work
public class CustomIocDependencyResolver : IDependencyResolver
{
private readonly CustomIoc container;
public ComponentLoaderWebApiDependencyResolver(CustomIoc container)
{
this.container = container;
}
IDependencyScope IDependencyResolver.BeginScope()
{
return new CustomIocDependencyResolver(container);
}
Object IDependencyScope.GetService(Type serviceType)
{
return container.GetInstance(serviceType);
}
IEnumerable<Object> IDependencyScope.GetServices(Type serviceType)
{
return container.GetAllInstances(serviceType);
}
public void Dispose()
{
}
}
now my katana Configuration looks like:
// This method is required by Katana:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var config = ConfigureWebApi();
config.DependencyResolver = CustomIocDependencyResolver(container);
// Use the extension method provided by the WebApi.Owin library:
app.UseWebApi(config);
}
being container the instance of my custom IoC
Since you mentioned AutoFac as a potential candidate, I recommend you follow their tutorial on WebAPI integration. You'll need to define an interface on CustomClass so that you can properly inject it.
You'll need to inject your instance that you've created (since you want to treat it as a singleton) by registering it as an instance component.
public interface ICustomClass {}
public class CustomClass : ICustomClass {}
public CustomClass _stuffInstance = new CustomClass();
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var builder = new ContainerBuilder();
var config = new HttpConfiguration();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterInstance(_stuffInstance).As<ICustomClass>();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
Then, in each controller's constructor, inject your instance that's been bound to the appropriate interface.
public class CustomController : ApiController
{
private readonly ICustomClass _customClass;
public CustomController(ICustomClass customClass)
{
_customClass = customClass;
}
}
With ASP.NET Core 6 you can now register a service provider:
builder.Services.AddScoped<ICustomClass, CustomClass>(sp => new CustomClass()/* or your already existing instance */);
builder.Services.AddSingleton<ICustomClass>(sp => new CustomClass()/* or your already existing singleton instance */);
it will be injected to your controllers:
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
private readonly ICustomClass _customClass;
private readonly ILogger _logger;
public MyController(ICustomClass customClass, ILogger<MyController> logger)
{
_customClass = customClass;
_logger = logger;
}
Related
How to actually register IConnectionManager with some DependencyInjection implementation? (Unfortunely it is not Core)
I tried Autofac and some "manual" way to achieve it, but none of them works for me
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterType<IConnectionManager>().InstancePerRequest();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.MapSignalR();
}
There is no parameterless constructor defined for this object.
How can I then obtain SignalR's IConnectionManager in my controller?
private readonly IHubContext _hubContext;
public HomeController(IConnectionManager hubManager)
{
_hubContext = hubManager.GetHubContext<TestHub>();
}
You need not to inject IConnectionManager to your controller. You can get IConnectionManager from GlobalHost
GlobalHost.ConnectionManager:
Gets the default IConnectionManager.
Try below solution,
public HomeController
{
private static IHubContext HubContext { get; set; };
//Use static constructor, as getting hub context is an expensive operation
public static HomeController()
{
HubContext = GlobalHost.ConnectionManager.GetHubContext<TestHub>();
}
...
}
Note: As getting default IConnectionManger is an expensive task, use static property and static constructor to execute only once in your application.
I am using OWIN to self host a web api web service in a wpf desktop app that uses the galasoft mvvmlight framework. When I attempt to dependency inject one of my model data services into the web api controller I get an error about "Make sure that the controller has a parameterless public constructor".
I understand that a web api controller will not support dependency injection out of the box. I've seen numerous examples detailing how to provide a custom IDependencyResolver when using Unity, or writing your own. Is there a straightfoward way to set the DependencyResolver property of the web api startup class HttpConfiguration object using the mvvmlight SimpleIoc.Default?
As a workaround I am currently setting my dataservice by calling SimpleIoc.Default.GetInstance() in my api controller constructor. This works, and may be functionally the same as relying on an injection mechanism, but dependency injection seems more elegant.
public class webApiStartup {
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "FileServerApi",
routeTemplate: "{controller}/{filename}"
,defaults: new { Controller = "filesController" }
);
//*
//* The Following line of Code does not work. But intellisense suggests
//* that there is a conversion available ?
//*
config.DependencyResolver = (IDependencyResolver)SimpleIoc.Default;
appBuilder.UseWebApi(config);
}
}
//*
//* This constructor for the web api controller works
//* but it is not as elegant as dependency injection
//*
public class filesController : ApiController
{
ILocalDataService _LocalDataSvc = null;
public filesController() {
_LocalDataSvc = SimpleIoc.Default.GetInstance<ILocalDataService>();
}
The cast
config.DependencyResolver = (IDependencyResolver)SimpleIoc.Default;
will fail because SimpleIoc is not derived from IDependencyResolver.
Create a wrapper for the container that is derived from IDependencyResolver
public class SimpleIocResolver : IDependencyResolver {
protected ISimpleIoc container;
public SimpleIocResolver(ISimpleIoc container) {
if (container == null) {
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType) {
try {
return container.GetInstance(serviceType);
} catch(Exception) {
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType) {
try {
return container.GetAllInstances(serviceType);
} catch (Exception) {
return new List<object>();
}
}
public IDependencyScope BeginScope() {
return new SimpleIocResolver(container);
}
public void Dispose() {
//No Op
}
}
and use that when configuring
config.DependencyResolver = new SimpleIocResolver(SimpleIoc.Default);
The ApiController can then be refactored
public class FilesController : ApiController {
ILocalDataService _LocalDataSvc = null;
public FilesController(ILocalDataService svc) {
_LocalDataSvc = svc;
}
//...
provided that the dependencies have been registered with the container.
Reference Dependency Injection in ASP.NET Web API 2
I was having issues whereby my container was not being called in when registered in my global.asax, so I thought that this could be because I am now using an OWIN startup class. I've moved the instantiation of the container to this class now. I'm wondering whether this is appropriate to do:
[assembly: OwinStartup(typeof(Startup))]
namespace Namespace.WebApi
public class Startup : IDisposable
{
private readonly WindsorContainer _Container;
public Startup()
{
_Container = new WindsorContainer();
_Container.Install(FromAssembly.Named("Namespace.WebApi.Installers"));
}
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Services.Replace(typeof(IHttpControllerActivator),
new WindsorHttpControllerActivator(_Container));
/// other configuration
}
public void Dispose()
{
_Container.Dispose();
}
}
You can include the Owino NuGet package and use the RegisterForDisposal extension like this:
public void Configuration(IAppBuilder app)
{
/// (...)
app.RegisterForDisposal(_Container);
}
or you can look at how the method is implemented and make your own implementation.
I wish to inject a service into a custom class i have created> i have been using Dependency injection to inject the same service into my WebApi controllers but cannot seem to understand why it doesn't work in my "InputDataValidationModel" class
This is what i am trying to do:
public class InputDataValidationModel
{
private ISec300_EE_SubmissionRepository _service { get; set; }
public InputDataValidationModel(ISec300_EE_SubmissionRepository service)
{
_service = service;
}
}
In the Global.asax i registered the types as follow:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
// Register the Controllers that should be injectable
unity.RegisterType<SEC300_EE_SubmissionController>();
unity.RegisterType<InputDataValidationModel>();
unity.RegisterType<ISec300_EE_SubmissionRepository, Sec300_EE_SubmissionRepository>(new ContainerControlledLifetimeManager());
unity.RegisterType<IClientRepository, ClientRepository>(new ContainerControlledLifetimeManager());
// Finally, override the default dependency resolver with Unity
config.DependencyResolver = new IoCContainer(unity);
}
What I cant understand specifically is that this works perfectly when done in my controller below:
public class SEC300_EE_SubmissionController : ApiController
{
private ISec300_EE_SubmissionRepository _service;
public SEC300_EE_SubmissionController(ISec300_EE_SubmissionRepository service)
{
if (service == null)
{
throw new ArgumentNullException("service");
}
_service = service;
}
}
It does not work because controllers are instantiated by Web API, and when Web API creates a controller it calls BeginScope which is the entry point to call your IoC and proceeds to resolve and constructs objects for you.
In your case InputDataValidationModel is not used and may be for this reason you don't have the instance
update
Do you perhaps have any suggestions on how i would inject my service into InputDataValidationModel ?
Option 1
You can use IDependencyResolver take a look at this link Dependency Resolution with the Unity Container`'
And after this you can resolve your service like this
var instance =GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof (InputDataValidationModel));
Option 2
You might use service locator even it is an anti-pattern
static void Main(string[] args)
{
UnityServiceLocator locator = new UnityServiceLocator(ConfigureUnityContainer(
ServiceLocator.SetLocatorProvider(() => locator);
var a = ServiceLocator.Current.GetInstance<IFoo>();
var b = ServiceLocator.Current.GetInstance<IFoo>();
Console.WriteLine(a.Equals(b));
}
private static IUnityContainer ConfigureUnityContainer()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
return container;
}
Hope this help
I am trying to get Unity Container Dependency Injection working on a self-hosted owin app. I have added the Unity nuget package to my project, and have set up my UnityConfig class as follows:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDBContext,UniversalCoatingsDbContext>();
container.RegisterType<IUserRepository,UserRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Then, I set up my controller like this:
public class UserController : ApiController
{
private IUserRepository userRepo;
public UserController() {
Console.WriteLine("User controller default constructor");
}
//dependency injected value
public UserController(IUserRepository repo)
{
this.userRepo = repo;
Console.WriteLine("DI enabled constructor");
}
[HttpPost]
public JsonResult<MessageResponse> Register(UnhashedUser unhashed_user)
{
MessageResponse response = new MessageResponse();
if(ModelState.IsValid)
{
response = userRepo.createUser(unhashed_user);
}
else
{
response.message = "Invalid Request sent.";
}
return Json(response);
}
}
The UnityConfig.RegisterComponents() method is called at the end of my Startup class's Configuration() method (after all the middleware is setup). When I access this controller's URL, the parameterless constructor is always called, and thus the instance of IUserRepository is never resolved.
Am I missing some sort of configuration pattern? Any info greatly appreciated.
I modified my UnityConfig class to expose the container as a static variable. And then,
I added this to my startup class:
//set up dependency injection
UnityConfig.RegisterComponents();
config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(UnityConfig.container);
app.UseWebApi(config);