0

Hello all I've Added Unity to an MVC app. it seems that DI is working with the MVC Portion of the app but i cannot figure out why it wont work with the API part of the application.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name:"DefaultApi",
            routeTemplate:"api/{controller}/{id}",
            defaults: new {id = RouteParameter.Optional}
        );

        config.Formatters.Add(new JsonMediaTypeFormatter());
        config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling =
            Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.None;
    }
}

public static class UnityMvcActivator
{
    /// <summary>
    /// Integrates Unity when the application starts.
    /// </summary>
    public static void Start(HttpConfiguration configuration) 
    {
        FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));

        DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));

        // TODO: Uncomment if you want to use PerRequestLifetimeManager
        // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));


    }

    /// <summary>
    /// Disposes the Unity container when the application is shut down.
    /// </summary>
    public static void Shutdown()
    {
        UnityConfig.Container.Dispose();
    }
}

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Address", action = "Index", id = UrlParameter.Optional }
        );
    }

}

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            UnityMvcActivator.Start(GlobalConfiguration.Configuration);


        }

I am just trying to get a repository to work in the web api but i keep getting

An error occurred when trying to create a controller of type 'AddressSearchController'. Make sure that the controller has a parameterless public constructor.",

this error. I have seen a few posts about this. I have tried them and still cannot get this to work. Does anyone have any suggestions?

public class AddressSearchController:_SimpleController<Address>
    {
        public AddressSearchController(IRepository<Address> addressRepository) : base(addressRepository)
        {

        }

        [HttpPost]
        [Route("api/AddressSearch/Search")]
        public IHttpActionResult Search([FromBody] AddressSearchDto addressSearchDto)
        {
            var addresses = new List<Address>()
            {
                CreateAddress(1,"Main St", 123),
                CreateAddress(2,"Main St", 124),
                CreateAddress(3,"Main St", 125),
            };

            return Ok(addresses);
        }

        static Address CreateAddress(int id,string street, int houseNumber)
        {
            return new Address()
            {
                Id = id,
                StreetName = street,
                HouseNumber = houseNumber
            };

        }
    }

     public static void RegisterTypes(IUnityContainer container)
    {
        RegisterInstances(container);
    }

    private static void RegisterInstances(IUnityContainer container)
    {
        container.RegisterType<IAddressContext, AddressContext>();
        container.RegisterType(typeof(IRepository<>), typeof(Repository<>));

    }

using System;
using Address_Tracker.Data.Context;
using Address_Tracker.Data.Context.Interfaces;
using Address_Tracker.Data.Repositories;
using Unity;

namespace Address_Tracker
{
    /// <summary>
    /// Specifies the Unity configuration for the main container.
    /// </summary>
    public static class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container =
          new Lazy<IUnityContainer>(() =>
          {
              var container = new UnityContainer();
              RegisterTypes(container);
              return container;
          });

        /// <summary>
        /// Configured Unity Container.
        /// </summary>
        public static IUnityContainer Container => container.Value;
        #endregion

        /// <summary>
        /// Registers the type mappings with the Unity container.
        /// </summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>
        /// There is no need to register concrete types such as controllers or
        /// API controllers (unless you want to change the defaults), as Unity
        /// allows resolving a concrete type even if it was not previously
        /// registered.
        /// </remarks>
        public static void RegisterTypes(IUnityContainer container)
        {
            RegisterInstances(container);
        }

        private static void RegisterInstances(IUnityContainer container)
        {
            container.RegisterType<IAddressContext, AddressContext>();
            container.RegisterType(typeof(IRepository<>), typeof(Repository<>));

        }
    }
}

1 Answer 1

1

Your AddressSearchController should have a default constructor, or if you have no default / parameterless constructor, then please pass interfaces instead of concrete classes in AddressSearchController.

I believe you may have such a scenario:

public class AddressSearchController : ApiController
{
    public AddressSearchController(SomeClassParameter obj)
    {  
        //some code 
    }
}

What you want actually is ether this:

public class AddressSearchController : ApiController 
{
    public AddressSearchController() // add default ctor
    {  
    }
    public AddressSearchController(SomeClassParameter obj)
    {  
        //some code 
    }
}

or this:

Register the interface ISomeClassParameter for type SomeClassParameter in Unity

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    UnityConfig.RegisterComponents();                           // <----- Add this line
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}           

Register component:

container.RegisterType<ISomeClassParameter , SomeClassParameter >();

and do constructor injection :

public class AddressSearchController : ApiController 
{
    public AddressSearchController(ISomeClassParameter obj)
    {  
        //some code 
    }
}

Also, make sure you have the WebApi version of Unity

I tried it out, it worked for me:

enter image description here

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

13 Comments

I have added AddressSearchController above and I only have one parameter in it.
Did you register IRepository to a concrete type?
I mean does your container register your IRepsitory to some concrete implementation like this container.RegisterType<IRepository, SomeRepository >();?
@JamTay317 - Also your Application_Start is missing the line UnityConfig.RegisterComponents();
that is called in UnityMvcActivator.Start(GlobalConfiguration.Configuration);
|

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.