【问题标题】:N-tier web API application with autofac使用 autofac 的 N 层 Web API 应用程序
【发布时间】:2018-12-25 16:01:39
【问题描述】:

我使用 Autofac 的依赖注入开发 aspnet webapi 应用程序,但遇到了一个问题。

我创建了模型Order、它的存储库和工作单元

public class Order
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string UserId { get; set; }
        public int ServiceId { get; set; }
        public string Header { get; set; }
        public string Description { get; set; }
        public string City { get; set; }
        public string Address { get; set; }
        public int Price { get; set; }
        public string Name { get; set; }
        public string PhoneNumber { get; set; }
        public DateTime CompletedOn { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime UpdatedAt { get; set; }
    }

OrderRepository.cs

public class OrderRepository : IRepository<Order>
    {
        private ApplicationContext database;

        public OrderRepository(ApplicationContext database)
        {
            this.database = database;
        }

        public void Create(Order item)
        {
            database.Orders.Add(item);
        }

        public void Delete(int id)
        {
            var order = database.Orders.Find(id);
            if (order != null)
            {
                database.Orders.Remove(order);
            }
        }

        public Order Get(int id)
        {
            return database.Orders.Find(id);
        }

        public IEnumerable<Order> GetList()
        {
            return database.Orders;
        }

        public void Update(Order item)
        {
            database.Entry(item).State = EntityState.Modified;
        }
    }

UnitOfWork.cs

public class UnitOfWork : IUnitOfWork
    {
        private ApplicationContext database;
        private OrderRepository orderRepository;

        private bool disposed = false;

        public IRepository<Order> Orders
        {
            get
            {
                if (orderRepository == null)
                {
                    orderRepository = new OrderRepository(database);
                }

                return orderRepository;
            }
        }

        public UnitOfWork(ApplicationContext database)
        {
            this.database = database;
        }

        public async Task SaveAsync()
        {
            await database.SaveChangesAsync();
        }

        public virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    database.Dispose();
                }
                this.disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

然后我做了 OrderManager

public class OrderManager : IOrderManager
    {
        IUnitOfWork database;

        public OrderManager(IUnitOfWork database)
        {
            this.database = database;
        }

        public void CreateOrder(OrderViewModel order)
        {
            database.Orders.Create(new Order
            {
                UserId = order.UserId,
                Header = order.Header,
                Description = order.Description,
                City = order.City,
                Address = order.Address,
                Price = order.Price,
                Name = order.Name,
                PhoneNumber = order.PhoneNumber,
                CompletedOn = order.CompletedOn,
                CreatedAt = order.CreatedAt,
                UpdatedAt = order.UpdatedAt
            });
        }

        public Order GetOrder(int id)
        {
            return database.Orders.Get(id);
        }

        public IEnumerable<Order> GetOrders()
        {
            return database.Orders.GetList();
        }
    }

然后我尝试制作 inject 并且我认为这里的某个地方出错了,因为我写了这个。

public static void ConfigureContainer()
        {
            var builder = new ContainerBuilder();

            builder.RegisterControllers(typeof(User).Assembly);

            builder.RegisterType<ApplicationContext>().AsSelf().InstancePerRequest().WithParameter("connectionString", "DefaultConnection");
            builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
            builder.Register(c => new UnitOfWork(c.Resolve<ApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
            builder.RegisterType<OrderManager>().AsSelf().InstancePerRequest();
            //builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter("database", new ApplicationContext("DefaultConnection")); ;
            builder.RegisterType<UserStore<User>>().As<IUserStore<User>>().InstancePerLifetimeScope();
            builder.Register(c => new UserStore<User>(c.Resolve<ApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
            builder.RegisterType<RoleStore<IdentityRole>>().As<IRoleStore<IdentityRole, string>>().InstancePerLifetimeScope();
            //builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();

            builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>
            {
                DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ASP.NET Identity​")
            });

            var container = builder.Build();

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }

以及弹出错误的地方

 protected OrderManager orderManager;

        public ValuesController()
        { }

        public ValuesController(OrderManager orderManager)
        {
            this.orderManager = orderManager;
        }

        public OrderManager OrderManager
        {
            get
            {
                return orderManager;
            }
            set
            {
                orderManager = value;
            }
        }

public OrderViewModel Get(int id)
        {
            var order = OrderManager.GetOrder(id);

            var orderViewModel = new OrderViewModel
            {
                Header = order.Header,
                Description = order.Description,
            };

            return orderViewModel;
        }

当我收到订单时,网站会因为 OrderManager 为空而下降。我想我的 DI 实现有问题,但我仍然不知道如何解决它。

【问题讨论】:

标签: c# asp.net-mvc asp.net-web-api dependency-injection asp.net-identity


【解决方案1】:

我认为您的设置代码不正确。在 ConfigureCONtainer 中,执行此操作

 public static void ConfigureContainer()
        {
            var builder = new ContainerBuilder();

            // Get your HttpConfiguration.
            var config = GlobalConfiguration.Configuration;

            // Register your Web API controllers.
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            // OPTIONAL: Register the Autofac filter provider.
            builder.RegisterWebApiFilterProvider(config);

            // OPTIONAL: Register the Autofac model binder provider.
            builder.RegisterWebApiModelBinderProvider();


            builder.RegisterType<ApplicationContext>().AsSelf().InstancePerRequest().WithParameter("connectionString", "DefaultConnectionString");
            builder.Register(c => new UnitOfWork(c.Resolve<ApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
            builder.RegisterType<OrderManager>().AsSelf().InstancePerRequest();



            // Set the dependency resolver to be Autofac.
            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }

并且该方法应该在其他 API 配置代码之前调用,例如

  public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            ConfigureContainer();

            // Web API routes
            config.MapHttpAttributeRoutes();

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


        }


        public static void ConfigureContainer()
        {
            var builder = new ContainerBuilder();

            // Get your HttpConfiguration.
            var config = GlobalConfiguration.Configuration;

            // Register your Web API controllers.
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            // OPTIONAL: Register the Autofac filter provider.
            builder.RegisterWebApiFilterProvider(config);

            // OPTIONAL: Register the Autofac model binder provider.
            builder.RegisterWebApiModelBinderProvider();


            builder.RegisterType<ApplicationContext>().AsSelf().InstancePerRequest().WithParameter("connectionString", "DefaultConnectionString");
            builder.Register(c => new UnitOfWork(c.Resolve<ApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
            builder.RegisterType<OrderManager>().AsSelf().InstancePerRequest();



            // Set the dependency resolver to be Autofac.
            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }
    }

我可以看到在 Web Api 控制器中正确创建了实例

控制器代码是

public class ValuesController : ApiController
    {
        public ValuesController(OrderManager orderManager)
        {
            this.OrderManager = orderManager;
        }

        public OrderManager OrderManager { get; set; }


        [Route("orders")]
        public IHttpActionResult GetAll()
        {
            return Ok("Received");
        }

        [Route("orders/{id}")]
        public OrderViewModel Get(int id)
        {
            var order = OrderManager.GetOrder(id);

            var orderViewModel = new OrderViewModel
            {
                Header = order.Header,
                Description = order.Description,
            };

            return orderViewModel;
        }

【讨论】:

  • 如果我这样做会出现错误“尝试创建'ValuesController'类型的控制器时发生错误。确保控制器具有无参数的公共构造函数。”
  • 我认为它可以提供帮助,但是在尝试您的代码后出现新错误 System.NullReferenceException Owin.c__21.&lt;CreatePerOwinContext&gt;b__2_0(IdentityFactoryOptions1 选项,T 实例)+6 可能这种方法会破坏与用户的旧依赖关系和应用程序用户管理器
  • 非常感谢您的帮助。我用你的代码解决了问题。我在辅助项目中有 IoC,当我将构建器放入 webapiconfig 时它可以工作。不幸的是,现在 ApplicationUserManager 发生了错误,但这个问题是另一种意义上的。再次感谢您
猜你喜欢
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 2012-12-10
相关资源
最近更新 更多