如何使用 Ninject for DI 在 MVC 应用程序中使用 AsyncController?

发布于 2024-09-25 03:04:58 字数 3645 浏览 8 评论 0原文

有谁知道如何在使用 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 页面未找到错误。这就是我配置 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 :)

感谢您的帮助。

Does anyone know how to use an AsyncController in a mvc application that uses Ninject for DI?

AsyncController works fine when i dont use ninject but i cant make them work together.

I added following in my sitemodule but no go.

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

sorry for not explaining this in details.

my controller looks like this

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

and my global.asax looks like this

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

this works fine. but as soon as i use ninject (ninject 2.0 ) i get 404 page not found error when i try to access the index page. this is how i am configuring 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( )
        {

        }
    }

Do i need to bind anything on my sitemodule?

BTW i am using Jeff Prosise's example which he posted in his blog Here
you can download his demo application and try Ninject-ify it :)

Any help appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅黛梨妆こ 2024-10-02 03:04:58

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

It appears it's not working because the standard NinjectControllerFactory inserts a NinjectActionInvoker into the controller's ActionInvoker property. The NinjectActionInvoker is derived from ControllerActionInvoker. An AsyncController, however, uses ActionInvokers derived from AsyncControllerActionInvoker. for some reason, this causes the controller to not match the route, and it returns a 404.

The real fix would be a patch to Ninject to support construction of AsyncController with AsyncControllerActionInvokers.

However, in the meantime, here is a workaround:

in your Global.asax, add this override:

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

and then add this class for 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;
    }
}

this is a copy of the NinjectControllerFactory that leaves out the assignment of the ActionInvoker.

IF you have code that depends on dependencies being injected into your ActionFilters, you will need to create your own ActionInvoker that returns an AsyncControllerActionInvoker that uses Ninject. Look at the Ninject.Web.Mvc source for the NinjectActionInvoker.

策马西风 2024-10-02 03:04:58

就像 Dave 指出 Ninject 需要一个补丁来支持异步控制器一样,Remo 也表示他会尽快解决这个问题。同时您可以使用戴夫的解决方法或尝试这个。这是直接从马嘴里说出来的。我在 ninject 组中发布了一条消息,雷莫对此做出了回应。

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 @@ 命名空间
    Ninject.Web.Mvc
    如果(控制器==空)
    返回base.GetControllerInstance(requestContext,
    控制器类型);

    • var standardController = 控制器为
      控制器;
    • var asyncController = 控制器作为 AsyncController;
    • if (asyncController != null)
    • {
    • asyncController.ActionInvoker =
      CreateAsyncActionInvoker();
    • }
    • 其他
    • {
    • var standardController = 控制器为
      控制器;
    • if (standardController != null)
    • standardController.ActionInvoker =
      创建ActionInvoker();
    • }

    • if (standardController != null)

    • standardController.ActionInvoker =
      创建ActionInvoker();

       返回控制器; 
          } @@ -69,5 +77,14 @@ 命名空间 Ninject.Web.Mvc 
          { 
                  返回新的 NinjectActionInvoker(内核); 
          } 
      
    • }
      • ///
    • /// 创建操作调用程序。
    • ///
    • /// 动作调用者。
    • 受保护的虚拟 NinjectAsyncActionInvoker
      CreateAsyncActionInvoker()
    • {
    • 返回新的NinjectAsyncActionInvoker(内核);
    • }
    • } } \ 文件末尾没有换行符

    • 雷莫

Like dave pointed out a patch is needed for Ninject to support async controller and Remo says he'll work on it as soon as he has sometime. meantime you can use dave's workaround or try this. this is straight from horse's mouth. i posted a msg in ninject group and Remo responded with this .

AsyncControllers are currently not
supported. I'll add this as soon as I
have the time to implement it
properly. In the mean time you can use
apply the following changes to the
sources to add the support:

  1. Make a copy of NinjectActionInvoker name it NinjectAsyncActionInvoker and
    change base type to
    AsyncControllerActionInvoker

  2. Apply the following changes to 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();

                  return controller; 
          }  @@ -69,5 +77,14 @@ namespace Ninject.Web.Mvc 
          { 
                  return new NinjectActionInvoker(Kernel); 
          } 
      
    • }
      • ///
    • /// Creates the action invoker.
    • ///
    • /// The action invoker.
    • protected virtual NinjectAsyncActionInvoker
      CreateAsyncActionInvoker()
    • {
    • return new NinjectAsyncActionInvoker(Kernel);
    • }
    • } } \ No newline at end of file

    • Remo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文