I have used autofac ,mvc 4.0 .
I have registered the interfaces and modules in Application_Start of my mvc 4.0 application.
I have also used properties auto wired eg
protected void Application_Start()
{
//Other codes...
builder.RegisterType<Service>()
.As<IService>()
.InstancePerLifetimeScope()
.PropertiesAutowired());
builder.RegisterControllers(typeof (MvcApplication).Assembly)
.PropertiesAutowired();
...
}
However The dependencies are not resolved in the startup class, and the object is always null .
public class Startup
{
public IService MyService { get; set; }
public void Configuration(IAppBuilder app)
{
MyService.SomeMetod(3, "");
}
}
In above code I was expecting MyService to be an object , but its not so it is always null, Am I doing something wrong Please Help.
Please note that the di is working in controllers , it is not working in the startup class only !
I was expecting AutoFac to resolve dependency automatically as it does in the controller classes , It was solved using manual resolution as following:
var myService = (IService)DependencyResolver.Current.GetService(typeof(IService ));
Related
In my ASP.NET Core application, I get the following error:
InvalidOperationException: Unable to resolve service for type 'Cities.Models.IRepository' while attempting to activate 'Cities.Controllers.HomeController'.
I the HomeController I am trying to pass the Cities getter to the view like so:
public class HomeController : Controller
{
private readonly IRepository repository;
public HomeController(IRepository repo) => repository = repo;
public IActionResult Index() => View(repository.Cities);
}
I have one file Repository.cs that contains an interface and its implementation like so:
public interface IRepository
{
IEnumerable<City> Cities { get; }
void AddCity(City newCity);
}
public class MemoryRepository : IRepository
{
private readonly List<City> cities = new List<City>();
public IEnumerable<City> Cities => cities;
public void AddCity(City newCity) => cities.Add(newCity);
}
My Startup class contains the default-generated code from the template. I have made any changes:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
}
}
For the Dependency Injection framework to resolve IRepository, it must first be registered with the container. For example, in ConfigureServices, add the following:
services.AddScoped<IRepository, MemoryRepository>();
For .NET 6+, which uses the new hosting model by default, add the following in Program.cs instead:
builder.Services.AddScoped<IRepository, MemoryRepository>();
AddScoped is just one example of a service lifetime:
For web applications, a scoped lifetime indicates that services are created once per client request (connection).
See the docs for more information on Dependency Injection in ASP.NET Core.
We are getting this error in Entity frame work core database first approach. I followed below steps and error got resolved
Step 1: Check Your context class constructor should be like this
public partial class ZPHSContext : DbContext
{
public ZPHSContext(DbContextOptions<ZPHSContext> dbContextOptions)
: base(dbContextOptions)
{
}
}
Step 2: In Startup file
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<ZPHSContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("BloggingDatabase")));
}
Step 3: Connection string in appsettings
"ConnectionStrings": {
"BloggingDatabase": "Server=****;Database=ZPHSS;Trusted_Connection=True;"
}
Step 4: Remove default code in OnConfiguring method in context class
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
Other answers are CORRECT, however I was spinning up a new asp.net core 2.1.x project and got this error.
Ended up being a typo by ME.
So in my Controller instead of Correctly using the Interface like this
public HomeController(IApplicationRepository applicationRepository)
{
_applicationRepository = applicationRepository;
}
My typo had me using ApplicationRepository instead of its interface IApplicationRepository
Notice below, and so with NO ERRORS spotting the missing "I" was fun :/
public HomeController(IApplicationRepository applicationRepository)
{
_applicationRepository = applicationRepository;
}
Thus the controller was not resolving the DI...
A method like this needs to be added to your Startup:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//...
// Add application services.
services.AddTransient<IRepository, MemoryRepository>();
//..
}
Services should be registered before used.
UPDATE:
If you do not want to use DI on your application, just create and instance of MemoryRepository on the constructor of HomeController, like this:
public class HomeController : Controller
{
private IRepository repository;
public HomeController()
{
repository = new MemoryRepository();
}
public IActionResult Index()
{
return View(repository.Cities);
}
}
You have to add your implementation to DI (Dependeny Injection) section. For .Net Core Mvc, it would be like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase()
);
services.AddScoped<IRepository, MemoRepostory>();
}
This may not be helpful for your code sample but in my case the same error was a result of a circular dependency.
you have to register your repository like this
services.AddSingleton<IRepository, MemoryRepository>();
In my case, I was trying to access context through constructor. like here;
private readonly Context _context;
public ImageController(Context context)
{
_context = context;
}
But When I tried to access the context just by creating an instance of class, it worked like here;
Context c = new Context();
For me I am using visual studio 2022 and .NET 6
the solution was add the following line in the Program.cs file :
builder.Services.AddSingleton<IHISInterface<UserDetails>, UserDetailsRepository>();
There is one more possibility that, You might have sent wrong variable in the place while writing this HTTPPOST last part code
mine is
var categoryMap = _mapper.Map(categoryCreate);
if(!_categoryRepository.CreateCategory(categoryMap))
{
ModelState.AddModelError("", "Something went wrong while saving");
return StatusCode(500, ModelState);
}
return Ok("Successfully created");
in the if condition I passed the category as parameter instead of categoryMap
so please cross check
I've been looking through examples and documentation for Autofac, and can't see to get this working.
We have a helper class, Core.Helpers.Tokens with a property set up like this:
namespace Core.Helpers
{
public static class Tokens
{
private static IConfigurationManager ConfigurationManager;
public static string GetToken()
{
var sessionTokenName = ConfigurationManager.GetAppSetting("SessionTokenName");
return (string) HttpContext.Current.Session[sessionTokenName];
}
}
}
The configuration is designed like this:
namespace Core.Config
{
public interface IConfigurationManager
{
//...
}
public class WebConfigConfigurationManager : IConfigurationManager
{
//...
}
}
In our MVC Web app (which references and uses Core.Helpers, Startup.cs I'm trying to register IConfigurationManager for property injection.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// REGISTER CONTROLLERS SO DEPENDENCIES ARE CONSTRUCTOR INJECTED
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterFilterProvider();
builder.RegisterType<WebConfigConfigurationManager>().As<IConfigurationManager>().PropertiesAutowired();
RegisterTypes(builder);
// BUILD THE CONTAINER
var container = builder.Build();
var webConfig = container.Resolve<IConfigurationManager>();
// REPLACE THE MVC DEPENDENCY RESOLVER WITH AUTOFAC
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// REGISTER WITH OWIN
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
When the web code calls GetToken, ConfigurationManager is null. What am I missing?
One error is that your Tokens.ConfigurationManager is a private field, whereas property injection works with public properties.
Also, it must be an instance property, not static. So in the end it should be
public IConfigurationManager ConfigurationManager{get;set;}
But that would mean you'd also have to inject a Tokens instance, and that would make no longer a static helper class, you'll have to do some redesign, there are some options:
If you have an IConfigurationManager instance everywhere you expect to call GetTokens from you can pass that in as an input parameter to GetTokens()
You promote this static helper to a dependency (e.g. ITokenService ? ) that will be injected to everywhere it's needed. Instead of making it static,
you can use Autofac lifetime management to make it a singleton. (Probably the best solution)
The worst solution, but the smallest change, one that works without having to give up this being a static helper class, is to make the property use the DependencyResolver instead of injection, something like:
private static IConfigurationManager ConfigurationManager{ get { return DependencyResolver.Current.GetService();} }
You are resolving IConfigurationManager, You should be resolving WebConfigConfigurationManager.
If you have 5 classes that utilize IConfigurationmanager, resolving the interface does not tell autoface which concrete class you are wanting to utilize which has this interface.
I'm trying my hand at dependency injection for my RPG written in c# and some javascript.
I'm trying to inject a service into my controller but keep getting this error:
Error activating IdownloadService No matching bindings are available, and the type is not self-bindable.
In debug mode, it fails on this line with the above error in my CharacterController class:
public IdownloadService downloadService{ get; }
Here is the relevant code:
characterDownloadService.cs
namespace OrionRPG.Character.Downloads
{
public interface IdownloadService
{
Uri CharacterDownloadUri(int charId);
}
public class characterDownloadService : IdownloadService
{
public characterDownloadService()
{}
public const String CharacterServerUrl = "http://myUrl/Characters/";
public Uri CharacterDownloadUri(int charId)
{
var characterName = Character.Name(charId);
return new Uri(CharacterServerUrl + characterName);
}
}
}
CharacterController.cs
namespace OrionRPG.Api.Downloads
{
public class CharacterController
{
public IdownloadService downloadService{ get; }
//inject the service
public CharacterController(IdownloadService downloadService)
{
DownloadService = downloadService;
}
[Route("api/characters/download/{charId}")]
public IHttpActionResult GetCharacterDownload(int charId)
{
return Redirect(DownloadService.CharacterDownloadUri(charId));
}
}
}
Generally speaking, services need to be registered to a container before injection. Different dependency injection framework might have slightly different syntax, the principles are the same.
For example, if you are using Microsoft.Extensions.DependencyInjection, you will need to Register the service: In Startup.cs (ASP.NET Core), you will see a method named ConfigureServices, and you will need to register your service like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(); // Some code by template
...
// This line registers the IdownloadService; when injection happens, the service provider knows to create an implementation of characterDownloadService for requested IdownloadService.
services.AddTransient<IdownloadService, characterDownloadService>();
}
For more details, check this out.
1) As I understand you are trying to use ASP.NET WebApi and it is strange that CharacterController doesn't inherit ApiController
2) You need to use Dependency Injection container which will contains all mapping between interfaces and it's implementation. I would recommend to use Autofac as it is perfectly integrated with ASP.NET MVC and WebAPI. Here is a link with docs
I am using Autofac with MVC / Owin and WebApi.
Following Autofac documentation I am using the setup:
public static void Run(IAppBuilder application) {
ContainerBuilder builder = new ContainerBuilder();
HttpConfiguration configuration = GlobalConfiguration.Configuration;
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterModelBinders(typeof(MvcApplication).Assembly);
builder.RegisterModelBinderProvider();
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterFilterProvider();
builder.RegisterApiControllers(typeof(MvcApplication).Assembly);
builder.RegisterWebApiFilterProvider(configuration);
builder.RegisterType<Test>().As<ITest>().PropertiesAutowired();
IContainer container = builder.Build();
application.UseAutofacMiddleware(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
I then tested constructor and property injection on a controller:
public interface ITest { }
public class Test : ITest { }
public partial class HomeController : Controller {
private ITest _testConstructor { get; set; }
public ITest TestProperty { get; set; }
public HomeController(ITest testConstructor) {
_testConstructor = testConstructor;
}
public virtual ActionResult Index() {
var test = TestProperty;
}
}
So _testConstructor is injected and TestProperty is always null.
I even checked its value inside Index method and it is null ...
I tried different configurations and in different parts of the application and Property injection always fails ...
Can someone, please, help me out with this?
Update 1
Adding .PropertiesAutowired(); to RegisterController work for controllers but not for ViewPages.
I am using a ViewPageBase as follows:
public abstract class ViewPageBase : WebViewPage {
public ITest Test { get; set; }
} // ViewPageBase
public abstract class ViewPageBase<T> : WebViewPage<T> {
public ITest Test { get; set; }
} // ViewPageBase
And then in Autofac setup I have:
builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterType<Test>().As<ITest>();
builder.RegisterType<WebViewPage>().PropertiesAutowired();
builder.RegisterGeneric(typeof(WebViewPage<>)).PropertiesAutowired();
But when I access Test properties in my views it is null.
Why?
Update 2
If in my layout view I add:
#{
var test = DependencyResolver.Current.GetService<ITest>();
}
test is resolved correctly ...
Maybe is this a problem with Layout Pages and Autofac?
Update 3
I was able to replicate the problem and created a project in https://github.com/mdmoura/MvcAutofac
If you run the project there will be an error on _Layout master page on the second code line:
#SettingsA.Get()
#SettingsB.Get()
SettingsA is resolved in ViewPagePage using DependencyResolver and it works.
With SettingsB i am trying to use Property Injection and no luck.
Autofac configuration is in global.asax Application_Start.
Does anyone knows what might be wrong?
Properties injection is not done automatically in Autofac. You have to tell Autofac to inject properties on your controller registration.
builder.RegisterControllers(typeof(MvcApplication).Assembly)
.PropertiesAutowired();
See Property and Method Injection for more information on autowiring properties.
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
}