I've created a default MVC5 web application in Visual Studio 2013, and added in the StructureMap.MVC5 package from NuGet.
I've created an interface ITester and an implementation Tester, and my controller action takes an ITester as a parameter.
But when I run the project I get the error Cannot create an instance of an interface.
According to this is should just work. I also get the same result if I explicitly tell structuremap to use Tester for ITester (rather than relying on the default conventions).
I've used StructureMap.MVC4 with MVC4 web applications before with no problems.
Out of the box it's going to do constructor injection only.
This will work
public HomeController(ITester tester)
{
_tester = tester;
}
This will cause the error you are seeing
public ActionResult Index(ITester tester)
{
return View();
}
Related
The configuration method below doesn't get fired.
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(SCM.Web.Startup))]
namespace SCM.Web
{
public partial class Startup
{
public void Configuration(IAppBuilder builder) { }
}
}
I've followed all the hints from here and it's a new project, not an upgrade. I can't for my life see how to get it to stop on the breakpoint and I'm in need to get more suggestions on how to troubleshoot it.
It's an intranet application so there's no logging in. The identity gets set to the Windows credentials, instead. I need to assign the roles so that only certain users can access certain actions in the controllers. I'm usually applying OWIN and application cookies, so that's the method I'm trying to follow here, as well.
You need an OwinStartup attribute to tell Owin what method to call. From the docs:
Used to mark which class in an assembly should be used for automatic startup.
Add one to your project, before the namespace declaration:
[assembly: OwinStartup(typeof(Your.Namespace.Startup))]
namespace Your.Namespace
{
public partial class Startup
{
public void Configuration(IAppBuilder builder) { }
}
}
There are some other methods to let Owin know which method (described here) but this is the simplest and probably the most common.
If you are running the website on an external IIS or maybe on the "real" IIS installed on your computer (and not the one that is fired up when you start the run), then it's likely that you're missing the breakpoint because the debugger isn't attached to the process yet when you pass by.
I think that you can confirm it by either checking the settings of your solution and projects or simply adding this code to the method that you don't think that you pass through.
throw new Exception("Killroy was here...");
Given this code:
namespace Eisk.Controllers
{
public class EmployeesController : Controller
{
DatabaseContext _dbContext;
public EmployeesController(DatabaseContext databaseContext)
{
_dbContext = databaseContext;
}
public ViewResult Index()
{
var employees = _dbContext.EmployeeRepository;
return View(employees.ToArray());
}
Note that the constructor doesn't new up a database.
When accessed from a unit test I can inject a databaseContext and the controller will use that for the duration of the test. What I can't figure out is where this code is getting the database context it's using at run time. If I could find that out I might be able to figure out how to circumvent that behavior and have it use a mocked/in memory DB instead.
More explanation:
I don't have access to a legacy database for this application right now so I'm trying to Mock up an in memory data source that gets filled from xml files. That's why I need to be able to circumvent the default database context creation.
More Information:
Thanks for all the help so far you wonderful people you.
Steven seems to have directed me down the correct path.
In the Global.asax file is this call:
DependencyInjectorInitializer.Init();
Following that through the code I get to:
public static void Initialize()
{
_container = new UnityContainerFactory().CreateConfiguredContainer();
var serviceLocator = new UnityServiceLocator(_container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
DependencyResolver.SetResolver(new UnityDependencyResolver(_container));
}
At least that gets me headed in the right direction. Now I have to figure out how Unity is going about creating the context so I can do my intervention.
Let me plug the EISK MVC Employee Info Starter Kit here. It's a well thought out system developed by Mohammad Ashraful Alam Et al. that includes a well fledged example of how many of the new technologies fit together. MVC 5, Entity Framework 6, Unity, Authentication, OpenAuth, DI, Moq, and a couple of other things. Can be used as a template, general learning, or training.
Employee Info Starter Kit
With the default configuration of ASP.NET MVC, a controller should have a default constructor (i.e. a public constructor with no parameters). If not ASP.NET MVC will throw the following exception:
Type 'Eisk.Controllers.EmployeesController' does not have a default
constructor
If this however works, this means that you (or another developer) overwrote the default configuration by either using a custom IControllerFactory or custom IDependencyResolver. Most developers do this by using an open source Dependency Injection library (such as Simple Injector, Autofac or Castle Windsor). If you pull in the NuGet MVC integration packages for such library, it will usually do this configuration for you. So somebody on your team might have done this for you.
My advice is: talk to your team and ask them how they did this and which container they used and where you can find the configuration for that.
We are migrating from .aspx web application to MVC app.
Below is the problem while migrating:
I have a third party dll which contains static factory method to return instance by given Interface name.
Controller code:
IBus objBus = (IBus) ObjectFactory.GetInstance("IBus") as IBus;
Here, ObjectFactory is from third party dll with definition as below (no more code details are available on GetInstance method).
public class ObjectFactory
{
public ObjectFactory();
public static object GetInstance(string interfaceName);
}
GetInstance method works perfectly in .aspx application - objBus is created successfully.
But the same line (Controller code) when executed in MVC controller returns objBus as null.
Please suggest what could be the problem.
I guess it may be due to difference in architecture and/or page life cyle of .aspx and mvc apps.
Any suggestions on the problem are greatly appreciated.
I think you should reach out to your third party DLL provider and ask for documentation on how to work with ASP.NET MVC.
If I was you I would think about dropping that DLL using Unity for you dependency injection for an MVC Project. All you need to do is in the Application_Start method in the Global.asax use the UnityConfig and DependecyResolver to inject you instances of class in to any of your controller methods.
If you need details check out these great articles.
http://netmvc.blogspot.com/2012/04/dependency-injection-in-aspnet-mvc-4.html
http://dotnetslackers.com/articles/aspnet/Using-Microsoft-Unity-in-ASP-NET-MVC.aspx
http://www.codeproject.com/Articles/99361/How-To-Use-Unity-Container-In-ASP-NET-MVC-Framewor
I started a new ASP.NET MVC project and I'm using Ninject as my IOC controller.
As far as regular MVC Controllers goes - everything work fine and binding is done to the controller constructor as expected.
I've added a WEB API to my project and did pretty much the same thing. here is the API constructor:
public class DetailsController : ApiController
{
private IClientInfoRetriever _clientInfoRetriever;
public DetailsController(IClientInfoRetriever clientInfoRetriever)
{
_clientInfoRetriever = clientInfoRetriever;
}
.
.
.
// The rest of my methods
}
here is the Ninject binding:
Bind<IClientInfoRetriever>().To<ClientInfoRetriever>();
but when I try to access my API (just putting the URL in the browser for a get action) I get the following error:
An error occurred when trying to create a controller of type 'DetailsController'. Make sure that the controller has a parameterless public constructor.
It's expecting to get an empty constructor, but if I give it an empty constructor to use - it won't be initializing the object I need.
What am I doing wrong? does Ninject support web api?
Thanks
Install the proper Ninject Nuget package for WebAPI:
PM> Install-Package Ninject.Web.WebApi -Version 3.0.0.2
I am using the Nuget MVC3 integration package for Autofac with MVC4. It mostly works (constructor injection with Controllers is working great) but it does not inject registered services into action filter properties.
This is my registration in Global.asax.cs:
builder.RegisterType<AspNetMembershipProviderWrapper>().As(typeof(IUserService)).InstancePerHttpRequest();
// 5) action filters
builder.RegisterType<SetCultureAttribute>().As<IActionFilter>().PropertiesAutowired().SingleInstance();
builder.RegisterFilterProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Then in the SetCultureAttribute I have this:
public IUserService _userService { get; set; } // it doesn't get injected, null
Nor does this work in the constructor of the attribute:
_userService = DependencyResolver.Current.GetService<AspNetMembershipProviderWrapper>(); // always returns null
DependencyResolver.Current.GetService() also returns null for all other registered services when called within the action filter's constructor (I tried it out in the Debug windows to test it).
So I guess something is not working right. Is it ok to use MVC3 integration or should I use MVC4 Nuget package (which says it's for RC)?
Is there anything else I could try to make this work?
In order to get ActionFilter injection working you need to register the provider, which I don't see in your example:
builder.RegisterFilterProvider();
There is doc on that here:
http://code.google.com/p/autofac/wiki/MvcIntegration3
In either case, you registered the service as IUserService, so that's how you'd have to resolve it.
_userService = DependencyResolver.Current.GetService<IUserService>();
You don't need to register the attribute. Check the wiki link above for more.