NServiceBus/MVC injection - Autofac doesn't like IControllerFactory? - model-view-controller

all. I am getting started with NServiceBus and have a pretty good handle on the basics thanks to Pluralsight and the internet. I have an stock MVC 4 project and I have setup dependency injection for my controllers (thanks to this blog post).
Here is how I have my bus setup in Global.asax:
_bus = Configure.With()
.DefaultBuilder()
.ForMVC()
.Log4Net()
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.SendOnly();
I am assigning it to a local private variable because I need access to the bus in Global so I can do some stuff on Session_End. However, when I run, I get the following error:
The requested service 'System.Web.Mvc.IControllerFactory' has not been
registered. To avoid this exception, either register a component to
provide the service, check for service registration using
IsRegistered(), or use the ResolveOptional() method to resolve an
optional dependency.
According to my stack trace, the failure point is when Autofac tries to resolve the type. For the sake of sanity, I removed the private variable and used just the Configure statement, same thing. I also have Ninject wired up in this app because that is my IoC of choice. Thinking that it was interfering with Autofac in some way, I removed Ninject from the equation, still not working.
So my question is, what am I doing wrong? Am I missing something? This is my first time with NServiceBus, but from everything I've seen, this should just work. Any info would be super helpful. Thanks.

Have a look at our MVC4 sample (this is running against v4, the next major release):
https://github.com/NServiceBus/NServiceBus/tree/develop/Samples/Messaging.Msmq/MyWebClient

I found the solution from your code, John! Here was my issue. This is what I had in my Dependency Resolver Adapter:
public object GetService(Type serviceType)
{
_builder.Build(serviceType);
}
What I needed to do was what you did in your MVC4 example:
public object GetService(Type serviceType)
{
return (Configure.Instance.Configurer.HasComponent(serviceType)) ? _builder.Build(serviceType) : null;
}
Once I did that, it all sorted itself out. Thanks again for the help!

Related

MvvmCross resolving IoC dependencies

I am trying to figure out the whole Mvvm way of declaring singletons and especially ones that have IoC dependencies tied to them. In my particular example I have a UserService that requires an IDatabase and an IMvxMessenger as an IoC dependency.
The IDatabase is platform specific so In my Droid.UI project I have resolved this using the following code:
var database = new Database(new SQLitePlatformAndroid(), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "database.db"));
database.Initialize();
Mvx.RegisterSingleton<IDatabase>(database);
In my .Core project I have the following code:
var database = Mvx.Resolve<IDatabase>();
var messenger = Mvx.Resolve<IMvxMessenger>();
Mvx.RegisterSingleton<IUserService>(new UserService(database, messenger));
I am trying to wrap my head around this. What really is the Mvx.Resolve's job and how it works along with the resolving other dependencies. I have already tested the code above and it doesn't seem to be working so I know I am missing something important here.
Any help on this will be much appreciated, thank you in advance!
Follow this link to the Service Location and Inversion of Control page for MvvmCross and look at Constructor Injection and Lazy Singleton.
Instead of resolving the dependency when you register the next, have it be resolved when the UserService instance gets initialized.

ServiceLocatorImplBase.cs not found

When my WebAPI controller is called from a client, I run into the following errors:
ServiceLocatorImplBase.cs not found error
An exception of type 'Microsoft.Practices.ServiceLocation.ActivationException' occurred in Microsoft.Practices.ServiceLocation.dll but was not handled in user code
The WebAPI controllers use constructor injection to inject a repository dependency which should be resolved by StructureMap IoC. Interestingly, the same code runs fine on my another development machine. Here is my stack trace. Thanks for your help.
System.ArgumentNullException was unhandled by user code
HResult=-2147467261
Message=Value cannot be null.
Parameter name: httpContext
Source=System.Web
ParamName=httpContext
StackTrace:
at System.Web.HttpContextWrapper..ctor(HttpContext httpContext)
at WebApi2.DependencyResolution.StructureMapDependencyScope.get_HttpContext() in c:.........\WebApi2\DependencyResolution\StructureMapDependencyScope.cs:line 69
at WebApi2.DependencyResolution.StructureMapDependencyScope.get_CurrentNestedContainer() in c:.........\WebApi2\DependencyResolution\StructureMapDependencyScope.cs:line 55
at WebApi2.DependencyResolution.StructureMapDependencyScope.DisposeNestedContainer() in c:.........\WebApi2\DependencyResolution\StructureMapDependencyScope.cs:line 90
at WebApi2.DependencyResolution.StructureMapDependencyScope.Dispose() in c:.........\WebApi2\DependencyResolution\StructureMapDependencyScope.cs:line 85
at WebApi2.App_Start.StructuremapMvc.End() in c:.........\WebApi2\App_Start\StructuremapMvc.cs:line 44
Thanks for your reply. Both machines are running integrated mode. The error is really misleading and threw me off to a wrong track. I spent hours trying to find where this ServiceLocatorImplBase.cs resides. I happened to look into the deeply nested inner exceptions, and found that the inner most exception (5th level) complains some entities generated by POCO generator have no identity key. This is because I manually added the foreign key relationship among some entities with
public virtual RelatedEntity1 {get;set;}
public virtual RelatedEntity2 {get;set;}
without setting [key] attributes in the related entities. I am not sure if this can be fixed but the exception message should not lead people to the wrong track.
The problem you are running into is because you are attempting to resolve HttpContext at the point in time that the application is composed (typically done in the Application_Start event of Global.asax). HttpContext is part of the application's runtime state. It is null at the point in time when the application is being composed.
The reason why it seems to work in your development environment is likely because your development environment's application pool is running in classic mode. Most likely the other environments are (correctly) running in integrated mode. So, this is a design issue, not a problem with deployment as you might expect.
The solution is to use an Abstract Factory so you can defer instantiating of the HttpContextWrapper until runtime. Then you can inject the abstract factory rather than HttpContextWrapper into your services.
public interface IHttpContextFactory
{
HttpContextBase Create();
}
public class HttpContextFactory
: IHttpContextFactory
{
public HttpContextBase Create()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
See this answer and this answer for a complete examples including usage.

Use Container/DependencyResolver in other dll

I'm trying to get myself familiar with MVC3 and autofac but I've encountered small problem that I'm having trouble resolving.
I am using autofac integrated with MVC3 and all works well, pages are loading correctly, dependencies are being injected and that's cool. What's bugging me is how to use autofac's Container or MVC's DependencyResover in class library project.
I'm trying to create static class that will help me handle domain events. I simply want to be able to call the method with event parameter and everything should be handeled by this class. Here is code:
public static IContainer Container { get; set; }
public static void Raise<T>(T e) where T : IDomainEvent
{
foreach (var eventHandler in DomainEventManager.Container.Resolve<IEnumerable<EventHandlers.Handles<T>>>())
{
eventHandler.Handle(e);
}
}
As you can see it's pretty straightforward and everything would work great if it wasn't MVC approach. Some of my dependencies are registeres as InstancePerHttpRequest (NHibernate' session), while other are registered as InstancePerDependency or SingleInstance. Thus when I try to use container created in my UI project, I get exception that there is no httpRequest tag available.
How can i reuse the Container created in web project to get access to all of it's features, including InstancePerHttpRequest and httpRequest tag?
Or maybe there is other solution to my problem? I was thinking about using delegate function to obtain event handlers, but I cannot (can I?) create generic delegate that I would not need to initialize with concrete type at time of assignment.
Why I want to do this using static class is basically every entity and aggregate or service needs to be able to raise domain event. Injecting EventManager into every one of these would be troublesome and static class is exactly what would resolve all my problems.
If anyone could help me get my head around it I would be grateful.
Cheers, Pako
You shouldn't be referencing your container directly from your app code. This looks like the Service Locator anti-pattern. The correct action is to pass your objects the services they need to do their jobs, usually done through constructor parameters. BUT... if you are going to insist on depending on a global static, then at least model EventManager as a singleton, such that usage would look like:
EventManager.Current.Raise<SomeEvent>(someObject);
and then you can set EventManager.Current equal to a properly constructed instance when your app is initialized.

Ninject and Custom Membership provider Mvc3 [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inject repository to custom membership provider with Ninject
I have searched much about this topic too much the most close answer was here
MVC 3 ninject custom membership context disposed error
but I don't have any idea about the details all I have in my application is a domain contains my entities and abstraction for repositories and the implementation everything works fine when I use my Ninject binding like this
public class NinjectControllerFactory : DefaultControllerFactory{
readonly IKernel _kernel;
public NinjectControllerFactory(){
_kernel=new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType){
return controllerType == null
? null
: (IController) _kernel.Get(controllerType);
}
void AddBindings(){
_kernel.Bind<IŁSomeRepository>()
.To<EFSomeRepository>();
but I have no idea how to bind the customer membership provider I have read about this that I have to inject via a poperty but I don't know how, any ideas ?
First, you should be using Ninject.MVC3 rather than your own controller factory. Ninject.MVC3 takes care of hooking everything up, you just need to provide your mappings in App_Start\NinjectWebCommon.cs
Second, don't bother with using Ninject for Membership, unless you're using a custom membership provider. Even then, it's a lot less of a pain if you don't mix Ninject and Membership. I would suggest not bothering with it unless you really know what you're doing.
The problem is that Membership is a static class, that creates a static instance of the Membership Provider. This means it doesn't get destroyed at the end of the request. There are ways around this, but in general, it's just a lot easier to use Membership as-is than try to make it work with DI.
The question you linked to solves a specific problem, relating to injecting business logic into your custom membership provider. If you need to do this, then it might be a good choice. However, I find that most custom membership providers tend to be very simple.

Using StructureMap in ASP.NET MVC Areas

I'm using StructureMap for IoC and it works fine for regular controllers but I can't make it work with Areas. I have the following AccountController in Administration Area:
public class AccountController : Controller
{
private readonly IFormsAuthenticationService formsService;
private readonly IMembershipService membershipService;
public AccountController(IFormsAuthenticationService formsService, IMembershipService membershipService)
{
this.formsService = formsService;
this.membershipService = membershipService;
}
...
}
And here's the error:
System.InvalidOperationException: An error occurred when trying to create a controller of type 'Foo.Areas.Administration.Controllers.AccountController'. Make sure that the controller has a parameterless public constructor. ---> System.MissingMethodException: No parameterless constructor defined for this object.
Any help would be greatly appreciated!
EDIT
StructureMap couldn't resolve MembershipProvider.
Here's the solution:
For<MembershipProvider>().Use(Membership.Providers["AspNetSqlMembershipProvider"]);
I doubt that this is a problem with areas because I am using them happily. It is more likely a pure IOC issue. You get this error when one of the injected services cannot be resolved by your container, which has the consequence that the container cannot match a signature for the constructor and tries to fall back to the empty constructor, which doesn't exist, rightly.
So, my first instinct would be to make sure that the two injected services are available. It is possible that one of them did not get created properly; a common cause is that the Membership provider cannot connect to its database, or similar.
For diagnosing, in your global.asax, after the container has been created, see if you can manually resolve those two services. I don't know SM, but something like:
var s = container.Resolve<IMembershipService>();
Satisfy yourself that both those services can be resolved.

Resources