2012-10-26 52 views
3

这是我的控制器控制器没有默认的构造函数500内部服务器错误

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

,这是我RegisterServices方法NinjectWebCommon.cs

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

,把它在CreateKernel()方法NinjectWebCommon

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

小号uggestion库

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(); 
} 
+0

你能粘贴你的global.asax吗? – Kristof

+0

@Kristof - global.asax中的任何内容都不会影响此 –

+0

这是注册DI容器时常见的错误。看一下'DependencyResolver',以及如何将容器注册为依赖关系解析器。 – DarthVader

回答

2

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

暂时,直到雷莫获得将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<>)); 
+0

我安装Ninject.WebApi-RC,然后再次尝试,但同样的错误来了:( – Bitsian

+0

@Bitsian - 你删除您的自定义依赖解析器 –

+0

野应.....我应该在哪里做 – Bitsian

-1

你可能需要做一些依赖注入,所以你可以在您的SuggestionController构造函数中注入ISuggestionRepository参数。为此,您需要重写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()); 
} 
+0

Ninject模块和DefaultControllerFactory在哪个包中?我在这些错误... – Bitsian

+0

我使用的两个包... 使用Ninject;使用Ninject.Syntax的 ; – Bitsian

+0

提问者正在使用Ninject.MVC3,它使用Microsoft的WebActivator系统。它已经本身挂钩起来,因为它使用内置MVC3 + –

0

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

+0

否工作控制器也是ApiController – Bitsian

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书中得到。