2

ASP.NET MVC 3 アプリがあり、次の状況に遭遇しました。私のページには、そのページに固有の関連リンクを含むことができるサイドバーがあります。つまり、コントローラのタイプによって決定されます。リンクは、現在のページのコンテンツによって決定されます。

私はPhil Haack のブログ投稿に従って、このような動的なサイドバーのレンダリングHtml.Actionと別のコントローラーを使用しました。このアプローチが私に与える関心の分離が好きです。私のコントローラーはサイドバーについて何も知りません。これが本来あるべき姿です。

ここで、サイド バー自体をレンダリングするために呼び出されるアクションであるの派生型のインスタンスSideBarを myに挿入したいと考えています。SideBarControllerコントローラーごとに 1つの派生型があるSideBarため、次のようなコードを書きたいと思います。

kernel.Bind<SideBar>().ToMethod(_ => controllerName == "foo" 
                                         ? new FooSideBar(kernel.Get<UrlHelper>()) 
                                         : new BarSideBar(kernel.Get<UrlHelper>()));

しかし、そのコードの断片にはかなり多くの間違いがあります。特に、ラムダでコントローラー名を取得できないという事実と、3 番目のタイプのコントローラーが登場したときに何が起こるかという問題です。 4番目など。

インスタンスは常に に注入されるためWhenInjectedInto<T>()、は使用できないことに注意してください。 SideBarSideBarController

価値があるのは、のインスタンスSideBarが現在 Ninject Factory 拡張機能を介して作成されているため、関連するサイド バー バインディングは次のとおりです (これまでのアプローチが機能することを証明するためだけに、SideBar の実装をハード バインドしました)。

kernel.Bind<ISideBarFactory>().ToFactory().InRequestScope();
kernel.Bind<SideBar>().To<FooSideBar>().InRequestScope();

最後に、基本的に、派生型SideBarとコントローラー型の間に 1 対 1 のマッピングがあります。少し重複しているような気がしますが、コンポーネント間の関係を表しているので、問題ないと思います。

これはすべて、問題のこの部分に対する私のアプローチが間違っていると私に思わせるため、Ninject を使用してクリーンなソリューションを実現する方法についての提案を歓迎します。

4

3 に答える 3

3

回答してみますが、今はコンピューターの近くにいないので、少しあいまいになります。

基本的に、別のパラメーターを Html.Action に渡すことができるため、そのパラメーターがリクエストまたはリクエストから収集されたもの (コントローラー名や URL 部分など) の場合、それを使用して表示するサイドバーを決定できます。ファクトリをサイドバー コントローラーに挿入し、それを使用して正しいコントローラーを作成するか、その他の操作を行う必要がある場合がありますが、必要なサイドバーがわかれば、はるかに簡単になります。

于 2012-07-23T20:33:04.700 に答える
1

これがninjectを使用して可能かどうかはわかりませんが、ModelBindingを次のように使用しています:

public interface ISidebar
    {
    }
    public class Sidebar1 : ISidebar
    {
    }
    public class Sidebar2 : ISidebar
    {
    }


 public class SidebarModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var controller = controllerContext.RouteData.Values["Controller"];
            var action = controllerContext.RouteData.Values["Action"];

            switch (controller.ToString())
            {
                case "Home":
                    return new Sidebar1();

                default:
                    return new Sidebar2();

            }

            throw new NotImplementedException();
        }
    }


 public class TestController : Controller
    {
        public TestController()
        {
        }

        public string Index(ISidebar sidebar)
        {
            //Do something with it
            return "OK";
        }
    }

//Add to the Application_Start
ModelBinders.Binders.Add(typeof(ISidebar), new SidebarModelBinder());

編集: しばらく時間がかかりましたが、Ninject を使用して動作させることができました。

http://blog.voltje.be/2012/08/22/creating-a-dynamic-sidebar-with-asp-net-mvc-ninject/でお読みください。

于 2012-07-23T19:53:13.680 に答える
0

提案:

  • サイドバーを挿入しないでください。
  • 代わりに [サイドバー]ContentProvider を挿入します。
  • デフォルトの実装をグローバル asax に (要求ごとに) バインドし、必要に応じてコントローラーでバインドを解除して再バインドします。
于 2012-07-23T19:26:32.387 に答える