I am seeing an issue in using of unity in controller constructor. Here are the details -
In unit configuration (unity.config)– here is what I am doing –
container.RegisterType<ISessionWrapper, SessionWrapper>()
In the Controller constructor
public OnboardingController( ISessionWrapper sessionwrapper )
{
SessionWrapper = sessionwrapper;
}
SessionWrapper
public interface ISessionWrapper
{
string Brand { get; set; }
//string CurrenSessionCulture { get; set; }
}
public class SessionWrapper : ISessionWrapper
{
public string Brand
{
get;
set;
}
}
Error occuring in doing this
No parameterless constructor defined for this object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.****
When I change the Controller Constructor definition like this it is all working fine.
public OnboardingController()
: this(new SessionWrapper())
{
//
}
You need to use a custom ControllerFactory using Unity to resolve instances of your controller classes. The default ControllerFactory used by MVC requires that the controller classes have a parameterless constructor.
A custom ControllerFactory using Unity looks like
public class UnityControllerFactory : DefaultControllerFactory {
private readonly IUnityContainer _container;
public UnityControllerFactory (IUnityContainer container) {
_container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
if (controllerType != null) {
return _container.Resolve(controllerType) as IController;
}
else {
return base.GetControllerInstance(requestContext, controllerType);
}
}
}
On application start (normally in the global.asax) you register your ControllerFactory in the MVC Runtime using the following code
var container = // initialize your unity container
var factory = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(factory);
Related
I have a web project containing 3 layers: Web (MVC5), BusinessLayer, DataAccess. I use StructureMap 4, Structuremap.MVC5 and StructureMap.WebApi2 to provide the default IoC configuration.
This is my configuration:
public static class IoC {
public static IContainer Initialize() {
var container = new Container(c => c.AddRegistry<DefaultRegistry>());
return container;
}
}
public class DefaultRegistry : Registry {
public DefaultRegistry() {
this.IncludeRegistry<DataAccessLayerRegistry>();
this.IncludeRegistry<BusinessLayerRegistry>();
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
}
}
The DataAccessLayerRegistry and BusinessLayerRegistry don't really do anything apart from scanning their respective dlls with DefaultConventions
Everything else is as generated by templates.
I inject dependencies in such hierarchical way:
Web:
public class HomeController : Controller
{
private ITestClass _myTest;
public HomeController(ITestClass testClass)
{
_myTest = testClass;
}
}
BusinessLayer:
public class TestClass : ITestClass
{
public TestClass(ITestValueRepository repo)
{
}
}
DataAccess:
public class TestValueRepository : ITestValueRepository
{
IMyContext _dbContext;
public TestValueRepository(IMyContext dbContext)
{
_dbContext = dbContext;
}
}
This all works fine and the dependencies are resolved correctly but when there is an error in one of the constructors somewhere down the road, for example an error creating the IMyContext instance (which is an EntityFramework DbContext), I don't get to see the real exception that happened there (for example issue with EF configuration). Instead this is what I see:
No parameterless constructor defined for this object.
[InvalidOperationException: An error occurred when trying to create a
controller of type 'XXX.Web.Controllers.HomeController'. Make sure
that the controller has a parameterless public constructor.]
There is no inner exception nor additional stack trace info that could lead to the real problem. Why is StructureMap hiding the real exception? Is there any way that I can set the StructureMap configuration to make it throw the real exceptions?
I've met an exception while resolving the object using Unity container:
Message "Value cannot be null.\r\nParameter name: container"
Source "Microsoft.Practices.Unity" string
I have a Prism application where I have ServiceModule. ServiceModule just has interface and its implementation:
public interface ICommonService
{
string SomeStorage { get; set; }
}
public class CommonService : ICommonService
{
string fooStorage=DateTime.Now.ToString();
public string FooStorage
{
get
{
return fooStorage;
}
set
{
fooStorage = value;
OnPropertyChanged("FooStorage");
}
}
}
I create a single instance of ICommonService in ViewModelA of ModuleA. It works okay:
unityContainer = new UnityContainer();
unityContainer.RegisterType<ICommonService, CommonService>(new ContainerControlledLifetimeManager());
IMyService someFoo = unityContainer.Resolve<ICommonService>();
someFoo.FooStorage = "AAAOOOBBB";
Then I want to read this data in viewModelB of ModuleB. And this code throws an exception:
ICommonService someFoo = unityContainer.Resolve<ICommonService>();
string str=someFoo.FooStorage;
The exception says:
Message "Value cannot be null.\r\nParameter name: container"
Source "Microsoft.Practices.Unity" string
What am I doing wrong? Any help will be greatly appreciated!
Based on the error message that you get, most probably the value of unityContainer is null. Make sure that you initialize it correctly.
I am trying to develop an application, through a book, in WebApi. It is a simple application but whenever I am testing this application using fiddler, it is throwing error - {"Message":"An error occurred when trying to create a controller of type 'TasksController'. Make sure that the controller has a parameterless public constructor."}. I am using ninject for dependency injection. Here is some of my code:
public class NinjectConfigurator
{
public void Configure(IKernel container)
{
AddBindings(container);
}
private void AddBindings(IKernel container)
{
ConfigureLog4net(container);
ConfigureNHibernate(container);
ConfigureUserSession(container);
ConfigureAutoMapper(container);
container.Bind<IDateTime>().To<DateTimeAdapter>().InSingletonScope();
container.Bind<IAddTaskQueryProcessor>().To<IAddTaskQueryProcessor>().InRequestScope();
container.Bind<IAddTaskMaintenanceProcessor>().To<AddTaskMaintenanceProcessor>().InRequestScope();
}
}
public class TasksController : ApiController
{
private readonly IAddTaskMaintenanceProcessor _addTaskMaintenanceProcessor;
//public TasksController() { }
public TasksController(IAddTaskMaintenanceProcessor addTaskMaintenanceProcessor)
{
_addTaskMaintenanceProcessor = addTaskMaintenanceProcessor;
}
[Route("", Name="AddTaskRoute")]
[HttpPost]
public Task AddTask(HttpRequestMessage requestMessage, NewTask newTask)
{
var task = _addTaskMaintenanceProcessor.AddTask(newTask);
return task;
}
}
I am not sure why I am getting the error. I am following all the instructions of the book. Please help!!
The code - container.Bind().To() is binding interface with interface and that was the issue.When I did bind the interface with the implementation then the problem was gone. The new code is container.Bind().To(). Again thank you for the help. It was a typo.
I have gotten myself into an interesting situation, and i am confused since i think i am doing all the right stuff here... I am getting the following error:
The current type, Services.Interfaces.IKenticoService, is an interface and cannot be constructed. Are you missing a type mapping?
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The current type, Services.Interfaces.IKenticoService, is an interface and cannot be constructed. Are you missing a type mapping?
Source Error:
Line 113: throw new InvalidOperationException("Container on Global Application Class is Null. Cannot perform BuildUp.");
Line 114:
Line 115: container.BuildUp(this as T);
Line 116: }
Line 117:
Source File: c:\PROJECTS\CMS\CurentSprint\currentsprint\Source\WebProject\App_Code\Global\BasePage.cs Line: 115
and the error is generated by base page:
protected override void OnPreInit(EventArgs e)
{
InjectDependencies();
base.OnPreInit(e);
}
/// <summary>
/// This method is used to inject any controller related dependencies from
/// our existing web page.
/// </summary>
protected virtual void InjectDependencies()
{
HttpContext context = HttpContext.Current;
if (context == null)
return;
IContainerAccessor accessor = context.ApplicationInstance as IContainerAccessor;
if (accessor == null)
return;
IUnityContainer container = accessor.Container;
if (container == null)
throw new InvalidOperationException("Container on Global Application Class is Null. Cannot perform BuildUp.");
container.BuildUp(this as T);
}
I have the mappings in place:
namespace Core.DI
{
public static class UnityHelper
{
public static void ConfigureContainer(IUnityContainer container)
{
container.RegisterType<IPersonRegistrationService, PersonRegistrationService>();
container.RegisterType<ILoginService, LoginService>();
container.RegisterType<IKenticoCMSOfferService, KenticoCMSOfferService>();
container.RegisterType<IKenticoService, KenticoService>();
and then i have some other...
}
}
}
This method is called in side global Application Start method:
public void Application_Start(object sender, EventArgs e)
{
// Azure Application start init
AzureInit.Current.ApplicationStartInit();
CMSAppBase.CMSApplicationStart();
//CustomCode: Added for DI (Unity block)
try
{
//CustomCode: Create the unity container.
Container = new UnityContainer();
UnityHelper.ConfigureContainer(Container);
//mappings
EntityMapper.MapEntities();
}
catch (Exception ex)
{
//TODO: add call to error logger.
}
}
My KenticoService class is setup properly as well:
namespace BusinessLogic.Services
{
public class KenticoService : IKenticoService
{
#region User API Calls
public void HandleCmsUser(Person person, string userName)
{
...
}
public void HandleCmsUser(Person person, string userName, string oldUserName)
{
...
}
#endregion
}
}
Now the kentico service methods are called inside LoginService and PersonRegistrationService only. So in both the classes i have:
[Dependency]
public IKenticoService KenticoServiceInstance { get; set; }
Now we have two sites, our custom MVC solution and a CMS site. The services referenced above are in the projects that are inside our MVC solution. For CMS use, we copy the dlls over to the CMS solution. The MVC solution compiles and runs great. The CMS site is throwing this error and i have double checked that the correct dlls are being referenced here. Are you seeing something here that i may be missing?
I'm implementing Policy injection with web api and for DI we are using custom DependancyResolver. I have used InterfaceIntercept approach to implement policy injection. It is working fine in case of Classes(custom created classes) but Policy Injection is not being fired in case of ApiController.
To call Policy Injection with APIController, I have created an interface & implemented that with the controller. Sharing code below :
Also I would need to call policy with MessageHandlers as well.
Policy Injection code :
public class LogExceptionsCallHandler : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
IApplicationLogger logger = new ApplicationLogger();
logger.Log(LoggingLevel.TRACE, "Entering " + input.MethodBase.DeclaringType.FullName + "." + input.MethodBase.Name);
//// Perform the operation
var methodReturn = getNext().Invoke(input, getNext);
//// Method failed, go ahead
if (methodReturn.Exception != null)
return methodReturn;
//// If the result is negative, then throw an exception
logger.Log(LoggingLevel.TRACE, "Ending " + input.MethodBase.DeclaringType.FullName + "." + input.MethodBase.Name);
return methodReturn;
}
public int Order { get; set; }
}
Attribute code
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method)]
public class LogExceptionsAttribute : HandlerAttribute
{
public LogExceptionsAttribute()
{
}
public HandleLogging HandleLogging { get; set; }
public int RetryCount { get; set; }
public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
{
return new LogExceptionsCallHandler();
}
}
Interface code :This interface is being implemented by the ApiController
[LogExceptions]
public interface IRequestExecutionController : IHttpController
{
[LogExceptions]
HttpResponseMessage ExecuteRequest();
}
IRequestExecutionController interface is being implemented by the RequestExecutionController.
Registering type with unity :
container.RegisterType<IDDNPublicAPI.PassThrough.IRequestExecutionController, RequestExecutionController>("requestexecution");
Registering Intercept
container.Configure<Interception>().SetInterceptorFor<IDDNPublicAPI.PassThrough.IRequestExecutionController>(new InterfaceInterceptor());
As we have unity to resolve dependency, So we have created a controller factory class to handle Controller instance creation.
public class UnityControllerFactory : IHttpControllerActivator
{
private IUnityContainer container;
private readonly IControllerFactory innerFactory;
public UnityControllerFactory(IUnityContainer container)
: this(container, new DefaultControllerFactory())
{ }
public UnityControllerFactory(IUnityContainer container, IControllerFactory innerFactory)
{`enter code here`
this.container = container;
this.innerFactory = innerFactory;
}enter code here
public IHttpController Create(HttpRequestMessa`enter code here`ge request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = (IHttpController)this.container.Resolve(controllerType, controllerDescriptor.ControllerName.ToLower());
return controller;
}
}
And we have register this Controller factory in global config file. Same process is working for other classes but not working for the apicontroller.
Can any one suggest something on this ?
Web API Controllers are not intercept-able. But you can get the same result using a filter.
Here is a good post showing how you can do the logging in your controller using filters:
http://damienbod.wordpress.com/2013/09/15/aop-with-asp-net-web-api/
You can still use your logging interceptor to log any of your backend code.