Autofac not working after update - asp.net-mvc

I have updated Autofac.Mvc from version 3.2.1 to 3.3.0, i also updated all other packages including EF, MVC, WebActivatorEx etc and after update it is giving error on my controller
no parameterless constructor defined for this object
I put a breakpoint in my initialization class and i found that it is not even hitting the breakpoint. I've a separate dependency resolution layer in my project and this is the code for initialization class
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(IocConfig), "RegisterDependencies")]
namespace MyApp.Bootstrapper
{
public class IocConfig
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
const string nameOrConnectionString = "name=AppContext";
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterGeneric(typeof(EntityRepository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest();
builder.RegisterGeneric(typeof(Service<>)).As(typeof(IService<>)).InstancePerHttpRequest();
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerHttpRequest();
builder.Register<IEntitiesContext>(b =>
{
var logger = b.Resolve<ILogger>();
var context = new AspnetIdentityWithOnionContext(nameOrConnectionString, logger);
return context;
}).InstancePerHttpRequest();
builder.Register(b => NLogLogger.Instance).SingleInstance();
builder.RegisterModule(new IdentityModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
}
Please guide me with this.

The bootstrapper project bin dlls must be loaded with a web project dll ,so in the bootstrapper project >> select properties >> select build tab >> change output path to >> web project bin (ex:..\myApp.web\bin)

Related

How to use Automapper in ASP.NET MVC controller?

Edit #1 - Added a Unity Container to inject the mapper in the controller but facing the following error.
I have created AutoMapperConfig.cs file with the following code:
public static MapperConfiguration Configure()
{
MapperConfiguration mapperConfiguration = new MapperConfiguration(cfg => {
cfg.CreateMap<OrderDTO, Order>()
});
return mapperConfiguration;
}
Then in my global.asax.cs file under the Application_start method I added:
MapperConfiguration config = AutoMapperConfig.Configure();
IMapper mapper = config.CreateMapper();
var container = new UnityContainer();
container.RegisterInstance(mapper);
//or
//container.RegisterType<IMapper, Mapper>();
As per the documents I would do the following to use AutoMapper:
Order mapped_order = mapper.Map<Order>(orderdto);
Controller -
public class OrderController : Controller, IPersonalizable
{
private readonly IMapper _mapper;
public OrderController(IMapper mapper)
{
_mapper = mapper;
}
// GET:
public ActionResult Index()
{
Order mapped_order = _mapper.Map<Order>(order);
}
}
However, I am having trouble referencing "mapper" in my controller. I am missing some way to inject or reference it and I am struggling to understand how to do that.
Error -
IMapper No matching bindings are available, and the type is not self-bindable.Activation path: 2) Injection of dependency IMapper into parameter mapper of constructor of type OrderController<br> 1) Request for OrderController
Suggestions: 1) Ensure that you have defined a binding for IMapper.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.```

Net Core: access to appsettings.json values from Autofac Module

AspNet core app
1) Autofac module like that
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
//Register my components. Need to access to appsettings.json values from here
}
}
2) Module from step№1 registered into Startup.cs
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacModule());
}
How to access to appsettings.json values from AutofacModule? I need that for create my objects inside AutofacModule and using it for DI.
Need to change step №2
public void ConfigureContainer(ContainerBuilder builder)
{
//get settigns as object from config
var someSettings= Configuration.GetSection(typeof(SomeSettings).Name).Get<SomeSettings>();
//put settings into module constructor
builder.RegisterModule(new AutofacModule(someSettings));
}
I don't know is "best practise" way or not, but it works.
So currently trying this as well.
First thing is to get the necessary nuget packages, and add them as using statements at the top of your class.
using Microsoft.Extensions.Configuration.Json;
using Autofac;
using Autofac.Configuration;
using Autofac.Extensions.DependencyInjection;
In your Program.cs Main or Startup.cs...
public static IContainer Container { get; set; }
Main() or Startup()
{
// Add the configuration to the ConfigurationBuilder.
var config = new ConfigurationBuilder();
config.AddJsonFile("appsettings.json");
var containerBuilder = new ContainerBuilder();
// Register the ConfigurationModule with Autofac.
var configurationModule = new ConfigurationModule(config.Build());
containerBuilder.RegisterModule(configurationModule);
//register anything else you need to...
Container = containerBuilder.Build();
}
This will register the configuration module into your autoFac container, after which you can then use constructor injection to pass this round...
public class YourController
{
private readonly IContainer _config;
public YourController(IContainer configuration)
{
// Use IContainer instance
_config = configuration;
}
Hope that helps somewhat, if you get any further a different way then please share.

Autofac TypeLoadException when upgrading MVC 4 -> 5

Trying to upgrade a project from MVC3to MVC5,
the 3->4 part went well and I could run the project.
However, after updating probably everything for mvc5,
I'm getting an exception
Inheritance security rules violated by type: 'Autofac.Integration.Web.Mvc.AutofacControllerFactory'. Derived types must either match the security accessibility of the base type or be less accessible.
on this row of Application_Start()
InitContainerProvider();
the method being called:
protected void InitContainerProvider()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<PeriodsProxy>().As<IPeriods>().AsWcfProxy();
_containerProvider = new ContainerProvider(builder.Build());
var factory = new AutofacControllerFactory(_containerProvider);
ControllerBuilder.Current.SetControllerFactory(factory);
}
Try the following
protected void InitContainerProvider()
{
var builder = new ContainerBuilder();
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterType<PeriodsProxy>().As<IPeriods>().AsWcfProxy();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
_containerProvider = new ContainerProvider(builder.Build());
DependencyResolver.SetResolver(new AutofacDependencyResolver(_containerProvider.ApplicationContainer.BeginLifetimeScope()));
}
This example uses the package NuGet: Autofac.Mvc5

Autofac Azure Mobile Service integration issue

I gets '..make sure that the controller has a parameterless public constructor autofac..'
My controller:
public class AccountController : ApiController
{
private IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
...
}
My autofac configuration:
protected void Application_Start()
{
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<AccountService>().As<IAccountService>().InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
Whats wrong with my code?
Full error message:
Exception=System.InvalidOperationException: An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProj.Api.Controllers.AccountController' can be invoked with the available services and parameters:
Cannot resolve parameter 'MyProj.Engine.Services.Interfaces.IAccountService accountService' of constructor 'Void .ctor(MyProj.Engine.Services.Interfaces.IAccountService)'.
Fixed myself. Actually the issue was that project is Azure Mobile Service.
It was my first experience with it and I have configured it as I used to do for WebApi. But as I understood after last googling this project type base on OWIN.
That's good article about: http://blogs.msdn.com/b/azuremobile/archive/2014/04/19/autofac-and-azure-mobile-services-net-backend.aspx
So it should be like this:
ConfigOptions options = new ConfigOptions();
ConfigBuilder builder = new ConfigBuilder(options, (httpConfig, autofac) =>
{
autofac.RegisterInstance(new MyService()).As<IMyService>();
});
HttpConfiguration config = ServiceConfig.Initialize(builder);

Web API & Simple Injector - Problem resolving Controller that was loaded from external dll

I am building a Web API using MVC4 Web API and Simple Injector that should expose a variety of CRUD and query operations. The reason for using IOC in my case is that we are a dev shop and I need to be able to let customers build their own web api controllers to expose the data they need to expose need from our system. Consequently, I was hoping to design my solution in a way that allowed me to dogfood my own product by making all the controllers, both ours and our customers', external and loadable through IOC.
The website does not have any reference to the library but the library contains controllers that I want to use in the website. I have the code finding the dll plugin and loading the controller type but when I try to navigate to the route that it would represent It says it can't find it.
i.e. if I try to navigate to /api/Test1Api I should see the text "hello world"
My problem here is that although I have loaded my controller type, I am unable to translate that into a route that the website says is there.
Here is how I register the container
[assembly: WebActivator.PostApplicationStartMethod(typeof(Spike.Web.Api.App_Start.SimpleInjectorInitializer), "Initialize")]
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
// Create the IOC container.
var container = new Container();
InitializeContainer(container);
container.RegisterMvcAttributeFilterProvider();
// Verify the container configuration
container.Verify();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
//DependencyResolver.SetResolver(new SimpleInjectorWebApiDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
var appPath = AppDomain.CurrentDomain.BaseDirectory;
string[] files = Directory.GetFiles(appPath + "\\bin\\Plugins", "*.dll",
SearchOption.AllDirectories);
var assemblies = files.Select(Assembly.LoadFile);
// register Web API controllers
var apiControllerTypes =
from assembly in assemblies
where !assembly.IsDynamic
from type in assembly.GetExportedTypes()
where typeof(IHttpController).IsAssignableFrom(type)
where !type.IsAbstract
where !type.IsGenericTypeDefinition
where type.Name.EndsWith("Controller", StringComparison.Ordinal)
select type;
// register MVC controllers
var mvcControllerTypes =
from assembly in assemblies
where !assembly.IsDynamic
from type in assembly.GetExportedTypes()
where typeof(IController).IsAssignableFrom(type)
where !type.IsAbstract
where !type.IsGenericTypeDefinition
where type.Name.EndsWith("Controller", StringComparison.Ordinal)
select type;
foreach (var controllerType in apiControllerTypes)
{
container.Register(controllerType);
}
foreach (var controllerType in mvcControllerTypes)
{
container.Register(controllerType);
}
}
}
I figured it out!
So I created a new class in my Web Api call CustomAssembliesResolver that inherits from DefaultAssembliesResolver. Essentially I add my assembly to the list of assemblies that are parsed when looking for controllers. I still have the code that uses Simple Injector for the DI portion of the solution.
public class CustomAssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
var appPath = AppDomain.CurrentDomain.BaseDirectory;
var baseAssemblies = base.GetAssemblies();
var assemblies = new List<Assembly>(baseAssemblies);
var files = Directory.GetFiles(appPath + "\\bin\\Plugins", "*.dll",
SearchOption.AllDirectories);
var customAssemblies = files.Select(Assembly.LoadFile);
// register Web API controllers
var apiControllerAssemblies =
from assembly in customAssemblies
where !assembly.IsDynamic
from type in assembly.GetExportedTypes()
where typeof(IHttpController).IsAssignableFrom(type)
where !type.IsAbstract
where !type.IsGenericTypeDefinition
where type.Name.EndsWith("Controller", StringComparison.Ordinal)
select assembly;
foreach (var assembly in apiControllerAssemblies)
{
baseAssemblies.Add(assembly);
}
return assemblies;
}
}
I also added the following line to the beginning of the App_Start in the Global.asax.cs
GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());
Hope this helps someone!

Resources