Hi
I want to use Autofac in my asp.net mvc appliation and here is the code I have in global.asxc file :
protected void Application_Start()
{
....
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
but when I run the project, I see this error :
This module requires that the HttpApplication (Global Application Class) implements IContainerProviderAccessor
what is wrong ?
I had the same problem as the OP, but my solution was different.
From here:
Remove Old Items
Remove IContainerProviderAccessor interface from Global.asax. This implementation is no longer used by ASP.NET MVC integration.
Remove references to the AutofacControllerFactory. The new MVC integration uses the MVC DependencyResolver class for integration instead.
Remove ASP.NET Autofac HTTP module configurations. Previously there were some Autofac ContainerDisposal and PropertyInjection modules required in your web.config. These should be removed.
A minimal global.asax.cs setup for autofac for asp.net mvc3 could look like this:
(RegisterRoutes is removed from the code). As opposed to previous versions of asp.net mvc (from http://code.google.com/p/autofac/wiki/Mvc3Integration)
the HttpApplication class no longer needs to implement the IContainerProviderAccessor interface as described in the ASP.NET Integration documentation. All code related to implementing the interface should be removed your Global.asax.cs file.
You will also need a reference to Autofac.Integration.Mvc.dll
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using Autofac.Integration.Mvc;
namespace ApplicationX
{
public class MvcApplication : HttpApplication
{
private static IContainer _container;
/// <summary>
/// Gets the container.
/// </summary>
public IContainer Container
{
get { return _container; }
}
// RegisterRoutes and RegisterGlobalFilters removed ...
/// <summary>
/// Fired when the first resource is requested from the web server and the web application starts
/// </summary>
protected void Application_Start()
{
// Register: create and configure the container
_container = BootstrapContainer();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
// MVC Stuff
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
/// <summary>
/// Fired when the web application ends
/// </summary>
public void Application_End()
{
// Release: remember to dispose of your container when your application is about to shutdown to let it gracefully release all components and clean up after them
_container.Dispose();
}
/// <summary>
/// Bootstrapper is the place where you create and configure your container
/// </summary>
/// <returns>An Autofac container</returns>
private IContainer BootstrapContainer()
{
var builder = new ContainerBuilder();
// You can make property injection available to your MVC views by adding the ViewRegistrationSource to your ContainerBuilder before building the application container.
builder.RegisterSource(new ViewRegistrationSource());
// An example of a module that registers the dependencies for a ServiceLayer of your application
builder.RegisterModule(new ServiceModule());
builder.RegisterControllers(typeof(MvcApplication).Assembly);
return builder.Build();
}
}
}
Related
I started creating a PoC following SO this post but I wasn't able to get a very basic sample to work.
What I did:
I created an ASP.NET MVC project using empty template and MVC references.
I added Bootstrapper, CustomControllerFactory and CustomViewEngine classes and also the corresponding lines in Application_Start.
I created an ASP.NET MVC project using MVC template.
I added the Export and PartCreationPolicy decorators on HomeController.
I published the module project to a folder inside /Modules directory -in WebHost root path.
What didn't work:
The method CompositionContainer.GetExportedValue throws an exception saying that it couldn't load one or more required types and that there is more information on LoaderExceptions property. That property is an array with 77 instances of what appears to be the same exception:
Could not load file or assembly Antlr3.Runtime, Version=3.4.1.9004, Culture=neutral, PublicKeyToken=eb42632606e9261f or one of its dependencies.
In FusionLog property I can see that the problem is related to the assembly version (see here).
I found a workaround for "solving" this by copying the dependentAssembly declarations from the module's web.config to the WebHost configuration file. However I'd like to avoid this as the WebHost should not be modified based on the module's needs.
Even after the workaround, it didn't work. While rendering the view, it threw this exception:
CS0234: The type or namespace name 'Optimization' does not exist in the namespace 'System.Web' (are you missing an assembly reference?)
For your help is share a full test project using MEF. visit this github link.
You need something like--
public class AzRDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly CompositionContainer _container;
public AzRDependencyResolver(CompositionContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return this;
}
/// <summary>
/// Called to request a service implementation.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementation or null.</returns>
public object GetService(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var name = AttributedModelServices.GetContractName(serviceType);
var export = _container.GetExportedValueOrDefault<object>(name);
return export;
}
/// <summary>
/// Called to request service implementations.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementations.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var exports = _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
return exports;
}
public void Dispose()
{
}
}
I have a MVC project, where i want to register a singleton of a specific service.
When i use simpleinjector, i get an error in all of my other classes with multiple constructors and so on. How do i configure it so ONLY my wanted service is dependency injection and DI is disabled for everything else (like before i used the DI container)?
Example of an exception i get:
No registration for type AccountController could be found and an
implicit registration could not be made. For the container to be able
to create AccountController it should have only one public
constructor: it has 2.
But i don't want AccountController to use dependency injection?!
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
// Create IOC Container
var container = new Container();
// Register services
container.RegisterSingleton<IWebSocketHandler, WebSocketHandler>();
// Verify services
container.Verify();
// Store the container for use by the application
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
}
In the startup.cs, I want to define an extended ServiceProvider: It basically wraps the default IServiceProvider implementation.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
[...]
var servicesProvider = services.BuildExtendedServiceProvider();
return servicesProvider;
}
Here is the core extended service provider implementation
/// <summary>
/// Extends the native asp.net service provider
/// </summary>
public class ExtendedServicesProvider : IServiceProvider
{
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// Creates a new instance of <see cref="ExtendedServicesProvider"/> provider based on the native mvc <see cref="IServiceProvider"/>
/// </summary>
/// <param name="serviceProvider"></param>
public ExtendedServicesProvider(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
/// <inheritDoc />
public object GetService(Type serviceType)
{
var resolvedService = _serviceProvider.GetService(serviceType);
[...]
return resolvedService;
}
}
At startup, I can see that GetService is called for each service with "singleton" life time (great!!)
However, it is not called anymore after that, and the default ServiceProvider is called instead...
By the way, if I request the resolution of IServiceProvider, this is the native one that I get.
I would like my serviceProvider to replace completely the native one and to be called EVERY TIME.
Did I miss something??
Ok, I just checked the source code (I should have checked before posting the question sorry).
https://github.com/aspnet/DependencyInjection/blob/master/src/Microsoft.Extensions.DependencyInjection/ServiceProvider.cs
The build method adds by itself the IServiceProvider type with the native instance.
As there seem to have no way to modify it properly (without reflection on "_table" field I mean :-). It seems to me that the approach is clearly not good.
I think I'll try other dependency injection engines such as Autofac, but I really wanted to keep the native engine that seemed to me really light weight.
I have created project with an asp.net 5 web api template. The startup.cs file content is like this.
public class Startup
{
public Startup(IHostingEnvironment env)
{
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseMvc();
}
}
I want to use a IoC framework like Autofac, StructureMap and Ninject. But How can I change default web api dependency resolver with a framework?
For example StructureMap container is set like this:
var container = new StructureMap.Container(m=>m.Scan(x =>
{
x.TheCallingAssembly();
x.WithDefaultConventions();
}));
But can not set it in web api life.
Check out the StructureMap.Dnx project:
https://github.com/structuremap/structuremap.dnx
Usage
The package contains a single, public extension method, Populate.
It's used to populate a StructureMap container using a set of ServiceDescriptors or an IServiceCollection.
Example
using System;
using Microsoft.Extensions.DependencyInjection;
using StructureMap;
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddWhatever();
var container = new Container();
// You can populate the container instance in one of two ways:
// 1. Use StructureMap's `Configure` method and call
// `Populate` on the `ConfigurationExpression`.
container.Configure(config =>
{
// Register stuff in container, using the StructureMap APIs...
config.Populate(services);
});
// 2. Call `Populate` directly on the container instance.
// This will internally do a call to `Configure`.
// Register stuff in container, using the StructureMap APIs...
// Here we populate the container using the service collection.
// This will register all services from the collection
// into the container with the appropriate lifetime.
container.Populate(services);
// Finally, make sure we return an IServiceProvider. This makes
// DNX use the StructureMap container to resolve its services.
return container.GetInstance<IServiceProvider>();
}
}
Documentation here might help:
http://docs.asp.net/en/latest/fundamentals/dependency-injection.html#replacing-the-default-services-container
I'm currently working on a project whereby I will be developing views that will be pre-compiled and will be part of an external MVC 3.0 web solution I do not have any control over.
Part of my requirements is that I will need to access an underlying database in order to get some data. I would like to use Ninject (I've been informed that's what the external solution uses) to inject the database instance into my controllers as necessary.
I understand that you add the bindings in such a place as the Global.asax however I do not have access to this as that is part of the external solution out of my control.
Is there anyway I can create this dependency injection in my project that contains the pre-compiled views etc and ensure it is resolved when the external project loads our controller?
If this is too vague let me know and I'll try and offer more information.
EDIT:
Initially upon taken on Darin's suggestion I got the exception below:
System.InvalidOperationException crossed a native/managed boundary
Message=Sequence contains no elements
Source=System.Core
StackTrace:
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:line 53
at Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:line 52
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:line 32
at Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:line 52
at MyApp.App_Start.NinjectWebCommon.Start() in C:\App\NinjectWebCommon.cs:line 28
InnerException:
However upon thinking about it, the bootstrapper should already be initialised in our external MVC application (assuming they are using this method I guess). So I don't need to do all the initialisation all I need to do is register my dependencies with the current Kernal.
Something like:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
RegisterServices(bootstrapper.Kernel);
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IDataContext>().To<ApiDataContext>();
}
}
When doing this I now get the items injected. However I'm not 100% this is the correct solution but it seems to work?
I understand that you add the bindings in such a place as the Global.asax
Not necessarily. Have you recently installed the Ninject.MVC3 NuGet in a new MVC application? If you haven't I invite you to do so now. Simply create a new ASP.NET MVC 3 project using the Internet Application template in Visual Studio and install this NuGet. Ready?
After doing that you will notice that the NuGet package created in App_Start folder to your project. It didn't touch at any Global.asax. Now let's inspect the contents of the NinjectWebCommon.cs file added to this folder:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]
namespace MvcApplication1.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
}
}
}
Notice the WebActivator's PreApplicationStartMethod and ApplicationShutdownMethodAttribute assembly attributes that allow you to plug code that executes when an ASP.NET application respectively starts and shuts down.
Alright, now simply put this code in your library and configure your kernel in the RegisterServices method.