4

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

当我不使用 ninject 时,AsyncController 工作正常,但我不能让它们一起工作。

我在我的站点模块中添加了以下内容,但没有成功。

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 page not found 错误。这就是我配置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-ify :)

任何帮助表示赞赏。

4

2 回答 2

2

似乎它不起作用,因为标准 NinjectControllerFactory 将 NinjectActionInvoker 插入到控制器的 ActionInvoker 属性中。NinjectActionInvoker 派生自ControllerActionInvoker. 然而,AsyncController 使用派生自AsyncControllerActionInvoker. 由于某种原因,这会导致控制器与路由不匹配,并返回 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,该 ActionInvoker 返回使用 Ninject 的 AsyncControllerActionInvoker。查看 NinjectActionInvoker 的 Ninject.Web.Mvc 源代码。

于 2010-10-01T16:00:54.693 回答
0

就像 dave 指出的那样,Ninject 需要一个补丁来支持异步控制器,而 Remo 说他会尽快处理它。与此同时,您可以使用 dave 的解决方法或试试这个。这是直接从马的嘴。我在 ninject 组中发布了一条消息,Remo 对此做出了回应。

当前不支持 AsyncController。只要我有时间正确实施它,我就会添加它。同时,您可以对源应用以下更改以添加支持:

  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" 索引 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 = 控制器作为控制器;
    • var asyncController = 控制器作为 AsyncController;
    • 如果(异步控制器!= null)
    • {
    • asyncController.ActionInvoker = CreateAsyncActionInvoker();
    • }
    • 别的
    • {
    • var standardController = 控制器作为控制器;
    • 如果(标准控制器!= null)
    • 标准控制器.ActionInvoker = CreateActionInvoker();
    • }

    • 如果(标准控制器!= null)

    • 标准控制器.ActionInvoker = CreateActionInvoker();

                  return controller; 
          }  @@ -69,5 +77,14 @@ namespace Ninject.Web.Mvc 
          { 
                  return new NinjectActionInvoker(Kernel); 
          } 
      
    • }
      • ///
    • /// 创建动作调用者。
    • ///
    • /// 动作调用者。
    • 受保护的虚拟 NinjectAsyncActionInvoker CreateAsyncActionInvoker()
    • {
    • 返回新的 NinjectAsyncActionInvoker(Kernel);
    • }
    • } } \ 文件末尾没有换行符

    • 雷莫

于 2010-10-02T12:14:06.557 回答