Autofac和ASP净MVC 4网页API [英] Autofac and ASP .Net MVC 4 Web API

查看:191
本文介绍了Autofac和ASP净MVC 4网页API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的 Autofac 作为国际奥委会在我的ASP.NET MVC 4项目。结果
Autofac是遇到了一些麻烦初始化存储库,并把它传递给 API控制器

我相信我缺少在我的配置的东西。我真的appriciate如果你能请点我朝着正确的方向:)

下面是我得到的错误,当我浏览到: https://开头本地主机:44305 / API /集成

 <错误>
    <消息方式>发生错误< /信息>
    < ExceptionMessage>
        构造函数没有发现'Autofac.Core.Activators.Reflection.DefaultConstructorFinder
        在类型'EL.Web.Controllers.API.IntegrationController'可以被调用
        可用的服务和参数:无法解析参数
        EL.Web.Infrastructure.IRepository`1 [EL.Web.Models.Integration]库的
        构造函数无效.ctor(EL.Web.Infrastructure.IRepository`1 [EL.Web.Models.Integration])。
    < / ExceptionMessage>
    < ExceptionType> Autofac.Core.DependencyResolutionException< / ExceptionType>
    <&栈跟踪GT;
        在Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext背景下,IEnumerable`1参数)
        在Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1参数)
        在Autofac.Core.Resolving.InstanceLookup.Execute()
        在Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope,IComponentRegistration注册,IEnumerable`1参数)
        在Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration注册,IEnumerable`1参数)
        在Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration注册,IEnumerable`1参数)
        在Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration注册,IEnumerable`1参数)
        在Autofac.ResolutionExtensions.TryResolveService(IComponentContext背景下,Service服务,IEnumerable`1参数,对象和放大器;实例)
        在Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext背景下,Service服务,IEnumerable`1参数)
        在Autofac.ResolutionExtensions.ResolveOptional(IComponentContext背景下,类型的serviceType,IEnumerable`1参数)
        在Autofac.ResolutionExtensions.ResolveOptional(IComponentContext背景下,类型的serviceType)
        在Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(类型的serviceType)
        在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HTT prequestMessage要求,类型controllerType,Func`1和放大器;激活)
        在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HTT prequestMessage要求,HttpControllerDescriptor controllerDescriptor,类型controllerType)
    < /堆栈跟踪>
< /错误>

下面是code的一些相关的位:

的IoC引导程序:

 公共静态类引导程序
{
    公共静态无效初始化()
    {
        VAR建设者=新ContainerBuilder();        builder.RegisterControllers(Assembly.GetExecutingAssembly());
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());        builder.Register(X =>新建SharePointContext(HttpContext.Current.Request))为<&ISharePointContext GT;()SingleInstance()。
        builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();
        builder.RegisterType&LT; SharePointContextFilter&GT;()SingleInstance()。        builder.RegisterFilterProvider();        集装箱的IContainer = builder.Build();
        DependencyResolver.SetResolver(新AutofacDependencyResolver(容器));        VAR解析器=新AutofacWebApiDependencyResolver(容器);
        GlobalConfiguration.Configuration.DependencyResolver =解析器;
    }
}

IRepository:

 公共接口IRepository&LT; T&GT;
{
    无效添加(T实体);    无效删除(INT ID);    IEnumerable的&LT; T&GT;查找(前pression&LT;&Func键LT; T,BOOL&GT;&GT;过滤器= NULL);    无效更新(INT ID,T实体);
}

SharePointRepository:

 内部类SharePointRepository&LT; T&GT; :IRepository&LT; T&GT;其中T:IEntity
{
    私人只读ISharePointContext _context;
    私人只读字符串_listName;    内部SharePointRepository(ISharePointContext上下文)
    {
        _context =背景;        [对象]属性= typeof运算(T).GetCustomAttributes(typeof运算(SharePointListAttribute),FALSE);        如果(!attributes.Any())
        {
            抛出新的异常(+ typeof运算(T)的定义没有收到相关的SharePoint列表);
        }        _listName =((SharePointListAttribute)属性[0])LISTNAME。
    }    公共无效添加(T实体)
    {
        抛出新NotImplementedException();
    }    公共无效删除(INT ID)
    {
        抛出新NotImplementedException();
    }    公共IEnumerable的&LT; T&GT;查找(前pression&LT;&Func键LT; T,BOOL&GT;&GT;过滤器)
    {
        抛出新NotImplementedException();
    }    公共无效更新(INT ID,T实体)
    {
        抛出新NotImplementedException();
    }
}

IntegrationController:

 公共类IntegrationController:ApiController
{
    私人只读IRepository&LT;集成和GT; _repository;    公共IntegrationController(IRepository&LT;集成和GT;库)
    {
        _repository =库;
    }    公共无效删除(GUID integrationId)
    {
        _repository.Delete(获取(integrationId).ID);
    }    公共IEnumerable的&LT;集成和GT;得到()
    {
        返回_repository.Find();
    }    公众获取集成(GUID integrationId)
    {
        返回_repository.Find(ⅰ= GT; i.IntegrationId == integrationId).FirstOrDefault();
    }    公共无效后([FromBody]集成集成)
    {
        _repository.Add(集成);
    }    公共无效认沽(GUID integrationId,[FromBody]集成集成)
    {
        _repository.Update(获取(integrationId).ID,集成);
    }
}

IEntity:

 内部接口IEntity
{
    INT标识{搞定; }
}

实体:

 公共抽象类实体:IEntity
{
    保护实体(INT ID)
    {
        ID = ID;
    }    公众诠释标识{搞定;私人集; }
}

集成:

  [SharePointList(集成)]
公共类集成:实体
{
    公共集成(INT标识):基座(id)的
    {
    }    公共字符串ApiUrl {搞定;组; }    公共BOOL DeletionAllowed {搞定;组; }    公众的Guid IntegrationId {搞定;组; }    公共字符串键{获得;组; }    公共字符串列表{搞定;组; }    公共BOOL OutgoingAllowed {搞定;组; }    公共字符串RemoteWeb {搞定;组; }    公共字符串的Web {搞定;组; }
}

非常感谢寻找到这一点:)


解决方案

您已经注册了您的 IRepository 错了。随着行:

<$p$p><$c$c>builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();

您告诉Autofac,每当有人将要求 IRepository&LT; IEntity&GT; 给他们一个 SharePointRepository&LT; IEntity&GT; ,但你要求一个具体的 IRepository&LT;整合方式&gt; ,所以你得到一个异常

您需要的是打开Autofac 通用的注册功能。因此,您的注册更改为:

  builder.RegisterGeneric(typeof运算(SharePointRepository&LT;&GT;))
       。至于(typeof运算(IRepository&LT;&GT;));

这将作为你所期望的,当你问一个 IRepository&LT;集成和GT; 它会给一个 SharePointRepository&LT;集成和GT;

您也有第二个不相关的问题:你的 SharePointRepository 只有一个内部构造

Autofac默认只查找公共的构造函数,所以你要么改变你的构造函数和类公共或你需要告诉给Autofac寻找与非公有制构造的 FindConstructorsWith 方法:

 建设者
    .RegisterType&LT; SharePointRepository&LT; IEntity&GT;&GT;()
    .FindConstructorsWith(
       新DefaultConstructorFinder(类型=&GT;
          type.GetConstructors(BindingFlags.NonPublic可| BindingFlags.Instance)))
    。至于&LT; IRepository&LT; IEntity&GT;&GT;();

I am using Autofac for IoC in my ASP .Net MVC 4 project.
Autofac is having some trouble initializing the repository and passing it to the API Controller

I am sure I am missing something in my configuration. I would really appriciate if you can please point me to the right direction :)

Here is the error I get when I navigate to: https://localhost:44305/api/integration

<Error>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>
        None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' 
        on type 'EL.Web.Controllers.API.IntegrationController' can be invoked with 
        the available services and parameters: Cannot resolve parameter 
        'EL.Web.Infrastructure.IRepository`1[EL.Web.Models.Integration] repository' of 
        constructor 'Void .ctor(EL.Web.Infrastructure.IRepository`1[EL.Web.Models.Integration])'.
    </ExceptionMessage>
    <ExceptionType>Autofac.Core.DependencyResolutionException</ExceptionType>
    <StackTrace>
        at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) 
        at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) 
        at Autofac.Core.Resolving.InstanceLookup.Execute() 
        at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) 
        at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) 
        at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) 
        at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) 
        at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) 
        at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters) 
        at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters) 
        at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType) 
        at Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType) 
        at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) 
        at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    </StackTrace>
</Error>

Here are some relevant bits of code:

IoC Bootstrapper:

public static class Bootstrapper
{
    public static void Initialize()
    {
        var builder = new ContainerBuilder();

        builder.RegisterControllers(Assembly.GetExecutingAssembly());
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        builder.Register(x => new SharePointContext(HttpContext.Current.Request)).As<ISharePointContext>().SingleInstance();
        builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();
        builder.RegisterType<SharePointContextFilter>().SingleInstance();

        builder.RegisterFilterProvider();

        IContainer container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        var resolver = new AutofacWebApiDependencyResolver(container);
        GlobalConfiguration.Configuration.DependencyResolver = resolver;
    }
}

IRepository:

public interface IRepository<T>
{
    void Add(T entity);

    void Delete(int id);

    IEnumerable<T> Find(Expression<Func<T, bool>> filter = null);

    void Update(int id, T entity);
}

SharePointRepository:

internal class SharePointRepository<T> : IRepository<T> where T : IEntity
{
    private readonly ISharePointContext _context;
    private readonly string _listName;

    internal SharePointRepository(ISharePointContext context)
    {
        _context = context;

        object[] attributes = typeof (T).GetCustomAttributes(typeof (SharePointListAttribute), false);

        if (!attributes.Any())
        {
            throw new Exception("No associated SharePoint list defined for " + typeof (T));
        }

        _listName = ((SharePointListAttribute) attributes[0]).ListName;
    }

    public void Add(T entity)
    {
        throw new NotImplementedException();
    }

    public void Delete(int id)
    {
        throw new NotImplementedException();
    }

    public IEnumerable<T> Find(Expression<Func<T, bool>> filter)
    {
        throw new NotImplementedException();
    }

    public void Update(int id, T entity)
    {
        throw new NotImplementedException();
    }
}

IntegrationController:

public class IntegrationController : ApiController
{
    private readonly IRepository<Integration> _repository;

    public IntegrationController(IRepository<Integration> repository)
    {
        _repository = repository;
    }

    public void Delete(Guid integrationId)
    {
        _repository.Delete(Get(integrationId).Id);
    }

    public IEnumerable<Integration> Get()
    {
        return _repository.Find();
    }

    public Integration Get(Guid integrationId)
    {
        return _repository.Find(i => i.IntegrationId == integrationId).FirstOrDefault();
    }

    public void Post([FromBody] Integration integration)
    {
        _repository.Add(integration);
    }

    public void Put(Guid integrationId, [FromBody] Integration integration)
    {
        _repository.Update(Get(integrationId).Id, integration);
    }
}

IEntity:

internal interface IEntity
{
    int Id { get; }
}

Entity:

public abstract class Entity : IEntity
{
    protected Entity(int id)
    {
        Id = id;
    }

    public int Id { get; private set; }
}

Integration:

[SharePointList("Integrations")]
public class Integration : Entity
{
    public Integration(int id) : base(id)
    {
    }

    public string ApiUrl { get; set; }

    public bool DeletionAllowed { get; set; }

    public Guid IntegrationId { get; set; }

    public string Key { get; set; }

    public string List { get; set; }

    public bool OutgoingAllowed { get; set; }

    public string RemoteWeb { get; set; }

    public string Web { get; set; }
}

Thanks a lot for looking into this :)

解决方案

You have registered your IRepository wrong. With the line:

builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();

You told Autofac that whenever somebody will request an IRepository<IEntity> give them a SharePointRepository<IEntity>, but you are requesting a concrete IRepository<Integration> so you get an exception.

What you need is the open generic registration feature of Autofac. So change your registration to:

builder.RegisterGeneric(typeof(SharePointRepository<>))
       .As(typeof(IRepository<>));

It will work as you would expect you when you ask for a IRepository<Integration> it will give a SharePointRepository<Integration>.

You also have a second unrelated problem: your SharePointRepository has only an internal constructor.

Autofac by default only looks for public constructors so you either change your constructor and class to public or you need to tell to Autofac to look for NonPublic constructors with the FindConstructorsWith method:

builder
    .RegisterType<SharePointRepository<IEntity>>()
    .FindConstructorsWith(
       new DefaultConstructorFinder(type => 
          type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance))) 
    .As<IRepository<IEntity>>();

这篇关于Autofac和ASP净MVC 4网页API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆