1

I have a Web API solution and I want to inject a class into my constructor of a Controller.

I am using UNity:

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var container = new UnityContainer();
        container.RegisterType<IDatabaseAdapter, DatabaseAdapter>(new HierarchicalLifetimeManager());
        config.DependencyResolver = new UnityResolver(container);

        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        var constraintResolver = new DefaultInlineConstraintResolver
                                 {
                                     ConstraintMap =
                                     {
                                         ["apiVersion"] = typeof(ApiVersionRouteConstraint)
                                     }
                                 };
        config.MapHttpAttributeRoutes(constraintResolver);
        config.AddApiVersioning();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

UnityResolver

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer _container;

    public UnityResolver(IUnityContainer container)
    {
        _container = container ?? throw new ArgumentNullException("container");
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return _container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return _container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = _container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        _container.Dispose();
    }
}

My controller.

[System.Web.Http.RoutePrefix("api/v{version:apiVersion}/measurements")]
[ApiVersion("1.0")]
public class MeasurementsController : Controller
{
    private readonly IDatabaseAdapter _databaseAdapter;
    [InjectionConstructor]
    public MeasurementsController(IDatabaseAdapter databaseAdapter)
    {
        _databaseAdapter = databaseAdapter;
    }
    [MapToApiVersion("1.0")]
    [System.Web.Http.Route("GetTrafficLights")]
    public JsonResult GetTrafficLights()
    {
        var trafficLights = TrafficLightCache.TrafficLightCache.TrafficLights();
        var result = new JsonResult
        {
            Data = JsonConvert.SerializeObject(trafficLights),
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
        return result;
    }
    [MapToApiVersion("1.0")]
    [System.Web.Http.Route("UpdateMeasurement")]
    public async Task<HttpStatusCodeResult> Update(string measurementToUpdate)
    {
        var measurement = JsonConvert.DeserializeObject<Measurement>(measurementToUpdate, new JsonSerializerSettings
        {
            DateTimeZoneHandling = DateTimeZoneHandling.Utc
        });
        await _databaseAdapter.Update(measurement);
        return new HttpStatusCodeResult(HttpStatusCode.Accepted);
    }
}

DatabaseAdapter

public class DatabaseAdapter : IDatabaseAdapter
{
   public async Task<Dictionary<int, CacheEntry>> MeasurementCache()
   { ... }

   public async Task Update(Measurement measurement)
   { ... }
}

IDatabaseAdapter

public interface IDatabaseAdapter
{
    Task<Dictionary<int, TrafficLightCache.CacheEntry>> MeasurementCache();
    Task Update(Measurement measurement);
}

The error says no parameterless constructor found. If I add an empty parameterless constructor it never fires the constructor which includes the IDatabaseAdapter injection so calls to Update always result in _databaseAdapter being null.

The stack trace is

[MissingMethodException: No parameterless constructor defined for this object.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +119
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +247
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
   System.Activator.CreateInstance(Type type) +11
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55

[InvalidOperationException: An error occurred when trying to create a controller of type 'APITest2.Controllers.V1.MeasurementsController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +76
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +88
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +194
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
6
  • The error says no parameterless constructor found. Please include a stacktrace / screenshot of the exception. Commented Aug 15, 2017 at 13:00
  • no parameterless constructor found of which class? Commented Aug 15, 2017 at 13:03
  • @ChetanRanpariya - MeasurementsController Commented Aug 15, 2017 at 13:05
  • @ChetanRanpariya - If I add the parameterless constructor, I don't get the error but the DatabaseAdapter isn't injected in and is always null. Commented Aug 15, 2017 at 13:05
  • I think the controller needs a parameterless constructor, try calling the constructor on your own from the parameterless constructor filled with the instance. Commented Aug 15, 2017 at 13:09

1 Answer 1

2

You need to user ApiController. Not Controller.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.