With the latest version of Unity (MVC5) the InjectionFactory has become deprecated. Below is the Obsolete warning you will receive when trying to use it.
[Obsolete("InjectionFactory has been deprecated and will be removed in next release. Please use IUnityContainer.RegisterFactory(...) method instead.", false)]
Unfortunately I lack the knowledge with this API to put in the appropriate fix.
As you can see from the code below I'm trying to register an IAuthenticationManager using the old solution which leverages InjectionFactory. Does anyone know how this would look with the new solution?
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
Below I've also included a controller which references this object.
public class AccountController : Controller
{
private AdAuthenticationService _signInService;
public AccountController() { }
public AccountController(IAuthenticationManager signInManager)
{
this._signInService = new AdAuthenticationService(signInManager);
}
etc...
Let me know if you all have any other questions and thanks for the help.
I feel a little stupid. I took the time to actually read the warning and the answer was right there.
One line replacement:
Old:
container.RegisterType<IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
New:
container.RegisterFactory<IAuthenticationManager>(c => HttpContext.Current.GetOwinContext().Authentication);
Related
Just upgraded from Microsoft.AspNet.OData 5.9.0 to 6.0.0.
The DefaultODataSerializerProvider class now has a constructor argument IServiceProvider.
I had a class NullSerializerProvider that implemented DefaultODataSerializerProvider.
This was adding a formatter to HttpConfiguration.
e.g.
public static void Register(HttpConfiguration config)
{
...
config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create(new
NullSerializerProvider(), new DefaultODataDeserializerProvider()));
}
My question:
NullSerializerProvider expects an instance of a class that implements IServiceProvider to be supplied. How do I supply this?
Here is the documentation on the OData dependency injection:
http://odata.github.io/odata.net/v7/#01-05-di-support
http://odata.github.io/WebApi/#13-04-DependencyInjection
I spent the whole day pouring over this information and trying to create my own IContainerBuilder around Ninject with no luck.
I finally gave up and let OData use its own DI container and keep that separate from my use of Ninject. I then realized I could create the DefaultContainerBuilder and register it like a custom container builder. I could then use the DefaultContainerBuilder to get the IServiceProvider.
var containerBuilder = new DefaultContainerBuilder();
config.UseCustomContainerBuilder(() => containerBuilder);
config.EnableDependencyInjection();
var serviceProvider = containerBuilder.BuildContainer();
var oDataSerializerProvider = new DefaultODataSerializerProvider(serviceProvider);
I also faced with this issue and after day of research find this solution:
using Microsoft.Extensions.DependencyInjection;
var serviceProvider = new ServiceCollection().BuildServiceProvider() as IServiceProvider;
Now you can create your own SerializerProvider or DeserializerProvider and use like:
var odataFormatters = ODataMediaTypeFormatters.Create(new DefaultODataSerializerProvider(serviceProvider), new JsonODataDeserializerProvider(serviceProvider));
config.Formatters.AddRange(odataFormatters);
Hope it save a lot of time and headache.
The action filter I want to inject into starts like this
public class UserAuthorisation : AuthorizeAttribute
{
public IWcfClientProxy<IAppFrameworkServiceChannel>
FrameworkServiceProxy { get; set; }
I have setup my container like this:
container.Register<IWcfClientProxy<IAppFrameworkServiceChannel>>(
()=> new WcfClientProxy<IAppFrameworkServiceChannel>());
container.RegisterInitializer<UserAuthorisation>(handler =>
{
handler.FrameworkServiceProxy = container
.GetInstance<IWcfClientProxy<IAppFrameworkServiceChannel>>();
});
When I run this the FrameworkServiceProxy property is null.
I have read this post: Simple Injector: Injecting a property in a base class and followed the answer. I have also read example in this page Simple Injector Documentation.
I am not injecting into a base class and maybe that is the issue?
## UPDATE ##
I am adding more information as I think it should be working from what has been said in Stevens answer.
I am using the NuGet package for MVC 3. This adds the following to the application:
public static class SimpleInjectorInitializer
{
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcAttributeFilterProvider();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IWcfClientProxy<IAppFrameworkServiceChannel>>(() => new WcfClientProxy<IAppFrameworkServiceChannel>());
container.RegisterInitializer<UserAuthorisation>(handler =>
{
handler.FrameworkServiceProxy = container.GetInstance<IWcfClientProxy<IAppFrameworkServiceChannel>>();
});
}
This includes the container.RegisterMvcAttributeFilterProvider(); that as I now understand it should register a filter provider and should mean that filters are created through the container (this understanding might be wrong) and then properties are automatically wired-up.
My filter is registered in the Global.asax.cs like so:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new UserAuthorisation());
}
It seems to me that the filter is not being created by the container so I think I need to do something else to get that to happen ?
I have selected Stevens answer as the answer as it got me to a solution and I am now using the command handler that he mentioned in the comments.
I have put a simple work around in to get my global filters injected.
In the App_Start\SimpleInjectorInitializer.cs I have added RegisterGlobalFilters like this:
public static void RegisterGlobalFilters(GlobalFilterCollection filters, Container container)
{
//Add simple injector resolved types.
filters.Add(container.GetInstance<UserAuthorisation>());
}
And in the Initialize method I have added this RegisterGlobalFilters(GlobalFilters.Filters, container);
The complete method looks like this:
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcAttributeFilterProvider();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
RegisterGlobalFilters(GlobalFilters.Filters, container);
}
As I said very simple. Just get my instances from simple injector and then add them to the global list, I am sure there are better ways to do this.
This way does mean you do not need to change the global.asax.cs which is possibly a good thing.
You are registering an initializer on your UserAuthorisation attribute. Initializers however, are only used by the container when a type is created by the container itself. Since attributes are created by the CLR, the initializer won't go off.
The SimpleInjector.Integration.Web.Mvc.dll (this NuGet package) contains a RegisterMvcAttributeFilterProvider extension method. This will register an AttributeFilterProvider that will do implicit property injection (and call into the container.InjectProperties method). After calling container.RegisterMvcAttributeFilterProvider(), you will see that this property is injected automatically.
I got Unity interception working using a HadlerAttribute and an instance of ICallHandler. To get it working all I have to do is decorate the class with the [Trace] attribute, and the interceptor works great.
[Trace]
public interface IPersonService
{
string GetPerson();
}
However I would like to have interception working for all my methods in a couple of assemblies. So I am using Unity AutoRegistration to set up my container as follows:
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
//container.AddNewExtension<UnityInterfaceInterceptionRegisterer>();
container.
ConfigureAutoRegistration().
ExcludeSystemAssemblies().
LoadAssemblyFrom(typeof(PersonService).Assembly.Location).
Include(If.ImplementsITypeName, Then.Register()).
ApplyAutoRegistration();
return container;
}
Works great, except when I attempt to setup global registration as per this post:
http://unity.codeplex.com/discussions/281022
I have a UnityContainerExtension configured as follows, where MVC4Unity is my DLL:
public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension
{
protected override void Initialize()
{
base.Container.AddNewExtension<Interception>();
base.Container.Configure<Interception>().
AddPolicy("LoggingPolicy").
AddMatchingRule<AssemblyMatchingRule>
(new InjectionConstructor("MVC4Unity")).
AddCallHandler(new TraceCallHandler());
base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);
}
private void OnRegister(object sender, RegisterEventArgs e)
{
IUnityContainer container = sender as IUnityContainer;
if (e != null && e.TypeFrom != null && e.TypeFrom.IsInterface)
{
container.Configure<Interception>()
.SetInterceptorFor(e.TypeFrom, e.Name, new InterfaceInterceptor());
}
}
}
Unfortunately it is always throwing a StackOverflowException (!) when it goes into the OnRegister method.
The question then is, has anyone implemented assembly or even namespace wide interception using Unity, and was this the way to go?
[EDIT]
It seems that no matter what I add in the AddMatchingRule line below, that the OnRegister handler is invoked for all included assemblies as well! ( for example even the Microsoft.* namespace assemblies!)
base.Container.AddNewExtension<Interception>();
base.Container.Configure<Interception>().
AddPolicy("LoggingPolicy").
// see what other types of matchings rules there are!
AddMatchingRule<NamespaceMatchingRule>
(new InjectionConstructor("MVC4Unity.*")).
AddCallHandler(new TraceCallHandler());
base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);
I'm late with my answer, but maybe someone will find this useful.
If I understood the problem correctly you need to apply one matching rule to multiple assemblies. For these kind of tasks you can use AssemblyMatchingRule (MSDN).
container.Configure<Interception>()
.AddPolicy("logging")
.AddMatchingRule<AssemblyMatchingRule>(
new InjectionConstructor(
new InjectionParameter("YourAssemblyName")))
.AddCallHandler<LoggingCallHandler>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(), new InjectionProperty("Order", 1));
In your last code snippet i think you need to remove dot asterisk in the end of namespace in order to add MVC4Unity namespace to your NamespaceMatchingRule.
For additional information please check this link - Policy Injection MSDN
In my project, I have the following PageCache entity, which is being stored in RavenDB:
public class PageCache
{
private readonly IHtmlDocumentHelper htmlDocumentHelper;
public string Id { get; set; }
public string Url { get; set; }
public PageCache(IHtmlDocumentHelper htmlDocumentHelper, string url)
{
this.htmlDocumentHelper = htmlDocumentHelper;
this.Url = url;
}
}
I am using Castle Windsor to inject the IHtmlDocumentHelper implementation at runtime. This member is used in methods defined inside the PageCache class, which I stripped from the above snippet for the sake of simplicity.
When I create a PageCache object using the constructor, everything works fine. But elsewhere in my code, I load PageCache objects back from RavenDB:
public PageCache GetByUrl(string url)
{
using (var session = documentStore.OpenSession())
{
return session.Query<PageCache>()
.Where(x => x.Url == url)
.FirstOrDefault();
}
}
My issue is that the objects I get back from RavenDB don't have the htmlDocumentHelper member set, rendering the PageCache methods that depend on it unuseable.
In other words: when I load objects back from documents stored in RavenDB, it won't use my constructor to build the objects, thus not initializing the private members through constructor injection.
Am I doing something wrong here? How would you solve such an issue?
I ended up using the solution proposed by Ayende below. The circular dependency issue I mentioned in the comments only appeared when I registered the DocumentStore in Windsor with UsingFactoryMethod(). The issue strangely disappeared when I used Windsor's DependsOn() and OnCreate() to configure and initialize the DocumentStore directly inside the Register().
My container is now being initialized as follows:
WindsorContainer container = new WindsorContainer();
container.Register(
// Register other classes, such as repositories and services.
// Stripped for the sake of clarity.
// ...
// Register the CustomJsonConverter:
Component.For<CustomJsonConverter>().ImplementedBy<CustomJsonConverter>(),
// The following approach resulted in an exception related to the circular
// dependencies issue:
Component.For<IDocumentStore>().UsingFactoryMethod(() =>
Application.InitializeDatabase(container.Resolve<CustomJsonConverter>()))
// Oddly enough, the following approach worked just fine:
Component.For<IDocumentStore>().ImplementedBy<DocumentStore>()
.DependsOn(new { Url = #"http://localhost:8080" })
.OnCreate(new Action<IDocumentStore>(store =>
store.Conventions.CustomizeJsonSerializer = serializer =>
serializer.Converters.Add(container.Resolve<CustomJsonConverter>())))
.OnCreate(new Action<IDocumentStore>(store =>
store.Initialize()))
.OnDestroy(new Action<IDocumentStore>(store =>
store.Dispose()))
);
Although it seems to be working fine, I feel odd having to call container.Resolve<CustomJsonConverter>() from inside the container.Register() method.
Is this a legal approach to register the dependencies?
Christian,
We can't use your ctor, we don't know what to put in there.
Instead, you can use this technique to tell RavenDB how to create your objects:
http://james.newtonking.com/projects/json/help/CustomCreationConverter.html
Then you can wire this in using documentStore.Conventison.CustomizeSerializer
Recently I've switched to Ninject 2.0 release and started getting the following error:
Error occured: Error activating SomeController
More than one matching bindings are available.
Activation path:
1) Request for SomeController
Suggestions:
1) Ensure that you have defined a binding for SomeController only once.
However, I'm unable to find certain reproduction path. Sometimes it occurs, sometimes it does not.
I'm using NinjectHttpApplication for automatic controllers injection. Controllers are defined in separate assembly:
public class App : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
INinjectModule[] modules = new INinjectModule[] {
new MiscModule(),
new ProvidersModule(),
new RepositoryModule(),
new ServiceModule()
};
return new StandardKernel(modules);
}
protected override void OnApplicationStarted()
{
RegisterRoutes(RouteTable.Routes);
RegisterAllControllersIn("Sample.Mvc");
base.OnApplicationStarted();
}
/* ............. */
}
Maybe someone is familiar with this error.
Any advice?
I finally figured this issue out recently. Apparently, the NinjectHttpApplication.RegisterAllControllersIn() function doesn't do all of the proper bindings needed. It binds your concrete controller implementations to IController requests. For example, if you have a controller class called SampleMvcController, which inherits from System.Web.Mvc.Controller. It would do the following named binding during application start:
kernel.Bind<IController>().To(SampleMvcController).InTransientScope().Named("SampleMvc");
But when debugging the NinjectControllerFactory, I find that request are being made for the Ninject Kernel to return an object for the class "SampleMvcController", not for a concrete implementation of IController, using the named binding of "SampleMvc".
Because of this, when the first web request that involves the SampleMvcController is made, it creates a binding of SampleMvcController to itself. This is not thread safe though. So if you have several web requests being made at once, the bindings can potentially happen more than once, and now you are left with this error for having multiple bindings for the SampleMvcController.
You can verify this by quickly refreshing an MVC URL, right after causing your web application to restart.
The fix:
The simplest way to fix this issue is to create a new NinjectModule for your controller bindings, and to load this module during application start. Within this module, you self bind each of your defined controllers, like so:
class ControllerModule : StandardModule {
public override Load() {
Bind<SampleMvcController>().ToSelf();
Bind<AnotherMvcController>().ToSelf();
}
}
But if you don't mind changing the Ninject source code, you can modify the RegisterAllControllersIn() function to self bind each controller it comes across.
I have been dealing with this problem for months. I tried so many options but was unable to come to a solution. I knew that it was a threading problem because it would only occur when there was a heavy load on my site. Just recently a bug was reported and fixed in the ninject source code that solves this problem.
Here is a reference to the issue. It was fixed in build 2.1.0.70 of the Ninject source. The key change was in KernelBase.cs by removing the line
context.Plan = planner.GetPlan(service);
and replacing it with
lock (planner)
{
context.Plan = planner.GetPlan(service);
}
To use this new build with MVC you will need to get the latest build of Ninject then get the latest build of ninject.web.mvc. Build ninject.web.mvc with the new Ninject build.
I have been using this new build for about a week with a heavy load and no problems. That is the longest it has gone without a problem so I would consider this to be a solution.
Are you sure you really are creating a single completely new Kernel from scratch in your OnApplicationStarted every time it's invoked ? If you're not and you're actually creating it once but potentially running the registration bit twice. Remember that you're not guaranteed to only ever have one App class instantiated ever within a given AppDomain.
My answer was a bit more obvious.
I had declared the binding for one of my controllers more than once during refactor of my code.
I added this to my global.ascx.cs file:
public void RegisterAllControllersInFix(Assembly assembly)
{
RegisterAllControllersInFix(assembly, GetControllerName);
}
public void RegisterAllControllersInFix(Assembly assembly, Func<Type, string> namingConvention)
{
foreach (Type type in assembly.GetExportedTypes().Where(IsController))
Kernel.Bind(type).ToSelf();
}
private static bool IsController(Type type)
{
return typeof(IController).IsAssignableFrom(type) && type.IsPublic && !type.IsAbstract && !type.IsInterface;
}
private static string GetControllerName(Type type)
{
string name = type.Name.ToLowerInvariant();
if (name.EndsWith("controller"))
name = name.Substring(0, name.IndexOf("controller"));
return name;
}
Then called it from my OnApplicationStarted() method as follows:
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
RegisterAllControllersInFix(Assembly.GetExecutingAssembly());
Difficult to know whether this fixed it though because it's so intermittent.