Controller没有默认构造函数500内部服务器错误

时间:2012-10-26 05:29:22

标签: c# asp.net-web-api ninject

这是我的控制器

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

答案 0 :(得分: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<>));

答案 1 :(得分:0)

我认为问题是你正在使用ApiController。 控制器和apiControllers使用不同的依赖注入容器。 然而,它们都暴露了相同的方法。
如果工作控制器继承了Controller类,那么这就是你的原因。
对于一个工作,看看 this topic

答案 2 :(得分: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一书中得到了这种技术。

答案 3 :(得分:-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());  
}