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

ISuggestionRepository

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

IserviceContext

 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

私は同じ問題に直面しました。

これが私が修正した方法です。コンテナーの静的ラッパーにすぎない 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 に答える
0

問題は、ApiController を使用していることだと思います。コントローラーと apiController は、異なる依存性注入コンテナーを使用しています。ただし、どちらも同じメソッドを公開しています。
作業中のコントローラが Controller クラスを継承している場合、それが原因です。
回避策については、 このトピックを参照してください

于 2012-10-26T06:05:12.517 に答える
-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 に答える