3 votes

Le contrôleur n'a pas de constructeur par défaut 500 internal server error

Voici mon contrôleur

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

et voici ma méthode RegisterServices dans 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>());
    } 

Mais j'obtiens une exception parce que mon contrôleur de suggestion n'a pas de constructeur par défaut et qu'il affiche un serveur interne 500 lorsque je touche le contrôleur depuis une application cliente.

Je sais que nous obtenons l'exception du contrôleur n'ayant pas de constructeur par défaut si la dépendance ninject ne fonctionne pas correctement, mais ci-dessous est un autre contrôleur que j'ai implémenté similaire au contrôleur de suggestion et il fonctionne absolument bien.

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

    }

}

Je ne sais pas où je me trompe. Faites-moi savoir si vous avez des suggestions.

EDIT :

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

    }

Le résolveur de dépendances que j'utilise

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

et l'appeler dans la méthode CreateKernel() dans 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;
    }

Dépôt de suggestions

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

}

Référentiel

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

2voto

Erik Funkenbusch Points 53436

Comme vous utilisez WebApi, vous devrez utiliser l'extension WebApi pour Ninject. Malheureusement, le paquet nuget actuel Ninject.WebApi n'est pas à jour et ne fonctionne pas avec la version publiée de WebApi.

Temporairement, jusqu'à ce que Remo mette à jour Ninject.WebApi à la version release, vous pouvez utiliser Ninject.WebApi-RC. http://nuget.org/packages/Ninject.Web.WebApi-RC

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

EDIT :

Pour récapituler les informations discutées dans les commentaires, voici les recommandations :

1) Utilisez Ninject.MVC3 et Ninject.Web.WebApi (mais utilisez Ninject.Web.WebApi-RC jusqu'à ce que l'officiel soit mis à jour) comme discuté ci-dessus. N'utilisez pas un DependencyResolver personnalisé, et laissez Ninject.Web.Mvc et .WebApi faire leur travail.

2) Modifiez vos fixations comme suit :

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

3) Ajouter une liaison générique pour votre ServiceContext

kernel.Bind(typeof(IServiceContext<>)).To(typeof(InMemoryDataContext<>));

0voto

Kristof Points 2931

Je pense que le problème est que vous utilisez le ApiController. Les contrôleurs et les apiControllers utilisent un conteneur d'injection de dépendances différent. Les deux exposent cependant les mêmes méthodes.
Si le contrôleur qui fonctionne hérite de la classe Controller, c'est la cause.
Pour une solution de contournement, consultez le site ce sujet

0voto

jaxxbo Points 339

J'ai rencontré le même problème.

Voici comment j'ai rectifié le tir : J'ai créé un WebContainerManager qui est juste une enveloppe statique autour du conteneur.

Les enveloppes de conteneurs statiques sont utiles lorsque vous ne contrôlez pas l'instanciation et ne pouvez pas compter sur l'injection - par exemple, les attributs des filtres d'action.

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

Dans votre contrôleur, appelez votre constructeur vide comme ceci, sans paramètres :

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

}

Cela devrait fonctionner.

Cette technique m'a été donnée par le livre sur MVC4 de Jamie Kurtz @jakurtz.

-1voto

John Gathogo Points 1791

Vous devez probablement procéder à une injection de dépendance afin de pouvoir injecter le fichier ISuggestionRepository sur votre SuggestionController constructeur. Pour ce faire, vous devez surcharger les méthodes de la classe DefaultControllerFactory afin de personnaliser la création des contrôleurs. Puisque vous utilisez NInject, vous pouvez avoir quelque chose comme :

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

Ensuite, dans votre Global.asax.cs, vous pouvez ajouter une ligne pour échanger la fabrique de contrôleur

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

    RegisterRoutes(RouteTable.Routes);
    ControllerBuilder.Current.SetControllerFactory(new NInjectControllerFactory());  
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X