如何在MVC应用程序中使用AsyncController和Ninject进行依赖注入?

4

有人知道如何在使用Ninject进行DI的mvc应用程序中使用AsyncController吗?

当我不使用ninject时,AsyncController运行正常,但我无法使它们共同工作。

我在我的sitemodule中添加了以下内容,但没有效果。

Bind<IAsyncController>( ).To<AsyncController>( ).InSingletonScope( );

抱歉没有详细解释。
我的控制器看起来像这样。
 [HandleError]
    public class HomeController : AsyncController
    {
        public void IndexAsync( )
        {
            AsyncManager.OutstandingOperations.Increment( );

            RssFeed feed = new RssFeed( );
            feed.GetRssFeedAsyncCompleted += ( s, e ) =>
                {
                    AsyncManager.Parameters[ "items" ] = e.Items;
                    AsyncManager.OutstandingOperations.Decrement( );
                };
            feed.GetRssFeedAsync( "http://feeds.abcnews.com/abcnews/topstories" );
        }

        public ActionResult IndexCompleted( IEnumerable<SyndicationItem> items )
        {
            ViewData[ "SyndicationItems" ] = items;
            return View( );
        }
    }

我的global.asax看起来像这样:
public class MvcApplication :  System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
        }
        protected void Application_Start( )
        {
            AreaRegistration.RegisterAllAreas( );
            RegisterRoutes( RouteTable.Routes );
        }
    }

这段代码本身没有问题。但是当我使用Ninject(Ninject 2.0)后,尝试访问主页时会出现404页面未找到的错误。以下是我如何配置Ninject:

public class MvcApplication : NinjectHttpApplication //System.Web.HttpApplication
    {
        #region IOC
        static IKernel container;
        public static IKernel Container
        {
            get
            {
                if ( container == null ) { container = new StandardKernel( new SiteModule( ) ); }
                return container;
            }
        }

        protected override IKernel CreateKernel( )
        {
            return Container;
        }
        #endregion

        public static void RegisterRoutes( RouteCollection routes )
        {
            routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
        }

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

        //    RegisterRoutes(RouteTable.Routes);
        //}

        protected override void OnApplicationStarted( )
        {
            AreaRegistration.RegisterAllAreas( );
            RegisterRoutes( RouteTable.Routes );
        }
    }

    public class SiteModule : NinjectModule
    {
        public override void Load( )
        {

        }
    }

我需要在我的网站模块上绑定什么吗?

顺便提一下,我正在使用Jeff Prosise在他的博客这里发布的示例,您可以下载他的演示应用程序并尝试将其Ninject化 :)

感谢任何帮助。


不提供任何关于错误的详细信息,然后抱怨没有人帮助你是不礼貌的。请提供关于实际发生情况的详细信息。描述您期望发生的事情以及实际发生的事情是一个好的开始。这里有很多熟悉Ninject的用户,他们可能会很乐意提供帮助。 - John Farrell
2个回答

2

看起来不起作用是因为标准的NinjectControllerFactory将NinjectActionInvoker插入到控制器的ActionInvoker属性中。NinjectActionInvoker源自ControllerActionInvoker。然而,AsyncController使用从AsyncControllerActionInvoker派生的ActionInvokers。由于某种原因,这导致控制器无法匹配路由,并返回404错误。

真正的解决方法是对Ninject进行修补,以支持使用AsyncControllerActionInvokers构建AsyncController。

但是,在此期间,您可以尝试以下解决方法:

在Global.asax中添加以下覆盖:

    protected override Ninject.Web.Mvc.NinjectControllerFactory CreateControllerFactory()
    {
        return new MyNinjectControllerFactory( kernel );
    }

然后为MyNinjectControllerFactory添加这个类:

public class MyNinjectControllerFactory : Ninject.Web.Mvc.NinjectControllerFactory
{
    public MyNinjectControllerFactory( IKernel kernel ) : base( kernel ) { }

    protected override IController GetControllerInstance( RequestContext requestContext, Type controllerType )
    {
        if ( controllerType == null )
        {
            // let the base handle 404 errors with proper culture information
            return base.GetControllerInstance( requestContext, controllerType );
        }

        var controller = Kernel.TryGet( controllerType ) as IController;

        if ( controller == null )
            return base.GetControllerInstance( requestContext, controllerType );

        //var standardController = controller as Controller;
        //if ( standardController != null )
        //    standardController.ActionInvoker = CreateActionInvoker();

        return controller;
    }
}

这是一个NinjectControllerFactory的副本,省略了ActionInvoker的分配。

如果您的代码依赖于将依赖项注入到ActionFilters中,您需要创建自己的ActionInvoker,返回使用Ninject的AsyncControllerActionInvoker。请查看Ninject.Web.Mvc源代码中的NinjectActionInvoker。


0

正如Dave所指出的,Ninject需要一个补丁来支持异步控制器,Remo说他会在有时间的时候尽快解决。与此同时,您可以使用Dave的解决方法或尝试这个。这是直接从消息来源得知的。我在Ninject组中发布了一条消息,Remo回复了这个。

AsyncControllers目前不受支持。我会尽快实现它,但在此期间,您可以应用以下更改来添加支持:
1.复制NinjectActionInvoker并将其命名为NinjectAsyncActionInvoker,并将基类型更改为AsyncControllerActionInvoker。
2.对NinjectControllerFactory应用以下更改:
diff --git "a/C:\Users\REMOGL~1\AppData\Local\Temp\ \NinjectControllerFactory_HEAD.cs" "b/C:\Projects\Ninject\ \ninject.web.mvc\mvc2\src\Ninject.Web.Mvc\ \NinjectControllerFactory.cs" index 2c225a1..3916e4c 100644 --- "a/C:\Users\REMOGL~1\AppData\Local\Temp\ \NinjectControllerFactory_HEAD.cs" +++ "b/C:\Projects\Ninject\ninject.web.mvc\mvc2\src\ \Ninject.Web.Mvc\NinjectControllerFactory.cs" @@ -53,10 +53,18 @@ namespace Ninject.Web.Mvc if (controller == null) return base.GetControllerInstance(requestContext, controllerType);
var standardController = controller as Controller; var asyncController = controller as AsyncController; if (asyncController != null) { asyncController.ActionInvoker = CreateAsyncActionInvoker(); } else { var standardController = controller as Controller; if (standardController != null) { standardController.ActionInvoker = CreateActionInvoker(); } }
if (standardController != null) { standardController.ActionInvoker = CreateActionInvoker(); } protected virtual NinjectAsyncActionInvoker CreateAsyncActionInvoker() { return new NinjectAsyncActionInvoker(Kernel); } }
请注意,这是一个专业术语的翻译,可能需要一定的编程知识才能理解。

嗯...我将Remo的回复添加为引用,并且它弄乱了差异。但是请前往Ninject Google组以查看他的回复http://groups.google.com/group/ninject/browse_thread/thread/93a82b94291ff2aa - user461943

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接