将Unity添加到MVC WebApi应用程序

时间:2018-03-31 18:20:27

标签: c# asp.net-web-api dependency-injection unity-container

大家好我已经为MVC应用添加了Unity。似乎DI正在使用应用程序的MVC部分,但我无法弄清楚为什么它不适用于应用程序的API部分。

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);


        }

我只是想让一个存储库在web api中工作,但我一直在

  

尝试创建类型为&#39; AddressSearchController&#39;的控制器时发生错误。确保控制器具有无参数的公共构造函数。&#34;,

这个错误。我看过几篇有关此事的帖子。我已经尝试过它们仍然无法使用它。有没有人有任何建议?

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 个答案:

答案 0 :(得分:1)

您的AddressSearchController应该有默认构造函数,或者如果您没有默认/无参数构造函数,那么请在AddressSearchController中传递接口而不是具体类。

我相信你可能有这样的场景:

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

你想要的实际上是以太:

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

或者这个:

ISomeClassParameter

中注册SomeClassParameter类型的界面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);
}           

注册组件:

container.RegisterType<ISomeClassParameter , SomeClassParameter >();

并进行构造函数注入:

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

另外,请确保您拥有WebApi version of Unity

我试了一下,它对我有用:

enter image description here