3

这是我的控制器

 public class SuggestionController : ApiController
{
    public ISuggestionRepository Repository { get; private set; }

    public SuggestionController(ISuggestionRepository repository)
    {
        this.Repository = repository;
    }

    // to post suggestion
    [HttpPost]
    [ActionName("PostSuggestion")]
    public HttpResponseMessage PostSuggestion(Suggestion suggestion)
    {
        var answerCorrect = this.Repository.CreateSuggestion(suggestion);

        if (answerCorrect == true)
            return Request.CreateResponse(HttpStatusCode.OK);
        else
            return Request.CreateResponse(HttpStatusCode.Conflict);
    }
}

这是我在 NinjectWebCommon.cs 中的 RegisterServices 方法

private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ICompetitionRepository>().To(typeof(CompetitionRepository))
            .WithConstructorArgument("serviceContext", new InMemoryDataContext<Competition>());

        kernel.Bind<ISubmissionRepository>().To(typeof(SubmissionRepository))
            .WithConstructorArgument("serviceContext", new InMemoryDataContext<Submission>());

        kernel.Bind<IUserRepository>().To(typeof(UserRepository))
            .WithConstructorArgument("serviceContext", new InMemoryDataContext<User>());

        kernel.Bind<ISuggestionRepository>().To(typeof(SuggestionRepository))
           .WithConstructorArgument("serviceContext", new InMemoryDataContext<Suggestion>());
    } 

但是我得到一个例外,即我的建议控制器没有默认构造函数,并且当我从客户端应用程序访问控制器时它显示 500 内部服务器

我知道如果 ninject 依赖项不能正常工作,我们会得到控制器没有默认构造函数的异常,但下面是我实现的另一个控制器,类似于建议控制器,它工作得非常好。

 public IUserRepository Repository { get; private set; }

    public SSOController(IUserRepository repository)
    {
        this.Repository = repository;
    }

    [HttpPost]
    [ActionName("PostUser")]
    public HttpResponseMessage PostUser([FromBody]string id)
    {
        var accessToken = id;
        var client = new FacebookClient(accessToken);
        dynamic result = client.Get("me", new { fields = "name,email" });
        string name = result.name;
        string email = result.email;


        var existingUser = this.Repository.FindByUserIdentity(name);

        if (existingUser == null)
        {
            var newUser = new User
            {
                Username = name,
                Email = email,

            };

            var success = this.Repository.CreateAccount(newUser);

            if (!success)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError);
            }

            //return created status code as we created the user
            return Request.CreateResponse<User>(HttpStatusCode.Created, newUser);
        }

        return Request.CreateResponse(HttpStatusCode.OK);

    }

}

我不知道哪里出错了。如果您有任何建议,请告诉我。

编辑:

我的 Global.asax

 public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        AuthConfig.RegisterAuth();

        GlobalConfiguration.Configuration.IncludeErrorDetailPolicy =
IncludeErrorDetailPolicy.Always;

    }

依赖解析器正在使用

 // Provides a Ninject implementation of IDependencyScope
// which resolves services using the Ninject container.
public class NinjectDependencyScope : IDependencyScope
{
    IResolutionRoot resolver;

    public NinjectDependencyScope(IResolutionRoot resolver)
    {
        this.resolver = resolver;
    }

    public object GetService(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has been disposed");

        return resolver.TryGet(serviceType);
    }

    public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has been disposed");

        return resolver.GetAll(serviceType);
    }

    public void Dispose()
    {
        IDisposable disposable = resolver as IDisposable;
        if (disposable != null)
            disposable.Dispose();

        resolver = null;
    }
}

// This class is the resolver, but it is also the global scope
// so we derive from NinjectScope.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
    IKernel kernel;

    public NinjectDependencyResolver(IKernel kernel)
        : base(kernel)
    {
        this.kernel = kernel;
    }

    public IDependencyScope BeginScope()
    {
        return new NinjectDependencyScope(kernel.BeginBlock());
    }
}

并在 NinjectWebCommon 的 CreateKernel() 方法中调用它

 private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);

        // Install our Ninject-based IDependencyResolver into the Web API config
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

        return kernel;
    }

建议库

 public class SuggestionRepository : Repository<Suggestion>, ISuggestionRepository
{
    public SuggestionRepository(IServiceContext<Suggestion> servicecontext)
        : base(servicecontext)
    { }

    public bool CreateSuggestion(Suggestion suggestion)
    {
        this.ServiceContext.Create(suggestion);
        this.ServiceContext.Save();

        return true;
    }
}

ISuggestion存储库

public interface ISuggestionRepository
{
    bool CreateSuggestion(Suggestion suggestion);

}

存储库

public abstract class Repository<T>
{
    public IServiceContext<T> ServiceContext { get; private set; }

    public Repository(IServiceContext<T> serviceContext)
    {
        this.ServiceContext = serviceContext;
    }
}

服务上下文

 public interface IServiceContext<T>
{
    IQueryable<T> QueryableEntities { get; }

    void Create(T entity);

    void Update(T entity);

    void Delete(T entity);

    void Save();
}
4

4 回答 4

2

由于您使用的是 WebApi,因此您需要为 Ninject 使用 WebApi 扩展。不幸的是,当前的 Ninject.WebApi nuget 包已经过时,并且不适用于已发布的 WebApi 版本。

暂时,在 Remo 开始将 Ninject.WebApi 更新到发布版本之前,您可以使用 Ninject.WebApi-RC http://nuget.org/packages/Ninject.Web.WebApi-RC

http://www.eyecatch.no/blog/2012/06/using-ninject-with-webapi-rc/

编辑:

回顾评论中讨论的信息,以下是建议:

1)如上所述使用Ninject.MVC3和Ninject.Web.WebApi(但在官方更新之前使用Ninject.Web.WebApi-RC)。不要使用自定义的 DependencyResolver,让 Ninject.Web.Mvc 和 .WebApi 完成它们的工作。

2)将您的绑定更改为:

kernel.Bind<ICompetitionRepository>().To<CompetitionRepository>();
... similar bindings

3) 为您的 ServiceContext 添加通用绑定

kernel.Bind(typeof(IServiceContext<>)).To(typeof(InMemoryDataContext<>));
于 2012-10-26T06:01:57.780 回答
0

我认为问题在于您使用的是 ApiController。控制器和 apiControllers 使用不同的依赖注入容器。然而,它们都暴露了相同的方法。
如果工作控制器继承了 Controller 类,那么这就是你的原因。
有关解决方法,请查看 此主题

于 2012-10-26T06:05:12.517 回答
0

我遇到了同样的问题。

这就是我纠正的方式:我创建了一个 WebContainerManager,它只是容器周围的一个静态包装器。

当您不控制实例化并且不能依赖注入时,静态容器包装器很有用 - 例如动作过滤器属性

public static class WebContainerManager
{
    public static IKernel GetContainer()
    {
        var resolver = GlobalConfiguration.Configuration.DependencyResolver as NinjectDependencyResolver;
        if (resolver != null)
        {
            return resolver.Container;
        }

        throw new InvalidOperationException("NinjectDependencyResolver not being used as the MVC dependency resolver");
    }

    public static T Get<T>()
    {
        return GetContainer().Get<T>();
    }
}

在你的控制器内部,像这样调用你的空构造函数,不带参数:

public SuggestionController() : this(WebContainerManager.Get<ISuggestionRepository>())
{

}

这应该有效。

我从 Jamie Kurtz @jakurtz 的 MVC4 书中获得了这项技术。

于 2013-03-31T00:50:11.387 回答
-1

您可能需要进行一些依赖注入,以便可以在构造函数中注入ISuggestionRepository参数。SuggestionController为此,您需要覆盖 DefaultControllerFactory 类中的方法来自定义控制器的创建。由于您使用的是 NInject,因此您可以使用以下内容:

public class NInjectControllerFactory : DefaultControllerFactory 
{
    private IKernel kernel = new StandardKernel(new CustomModule());

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        return controllerType == null ? null : (IController)kernel.Get(controllerType);  
    }

    public class CustomModule : NinjectModule
    {
        public override void Load()
        {
            this.Bind<ICompetitionRepository>().To(typeof(CompetitionRepository))
                .WithConstructorArgument("serviceContext", new InMemoryDataContext<Competition>());

            this.Bind<ISubmissionRepository>().To(typeof(SubmissionRepository))
                .WithConstructorArgument("serviceContext", new InMemoryDataContext<Submission>());

            this.Bind<IUserRepository>().To(typeof(UserRepository))
                .WithConstructorArgument("serviceContext", new InMemoryDataContext<User>());

            this.Bind<ISuggestionRepository>().To(typeof(SuggestionRepository))
               .WithConstructorArgument("serviceContext", new InMemoryDataContext<Suggestion>());
        }
    }
}

然后在您的 Global.asax.cs 中,您可以添加一行来换出控制器工厂

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterRoutes(RouteTable.Routes);
    ControllerBuilder.Current.SetControllerFactory(new NInjectControllerFactory());  
}
于 2012-10-26T05:43:20.467 回答