asp.net WebフォームにNinjectまたはDIを実装するにはどうすればよいですか?


回答:


79

WebFormsでNinjectを使用する手順は次のとおりです。

ステップ1-ダウンロード

Ninject-2.0.0.0-release-net-3.5とWebForm拡張機能Ninject.Web_1.0.0.0_With.log4netの2つのダウンロードが必要です(NLogの代替手段があります)。

次のファイルをWebアプリケーションで参照する必要があります:Ninject.dll、Ninject.Web.dll、Ninject.Extensions.Logging.dll、およびNinject.Extensions.Logging.Log4net.dll。

ステップ2-Global.asax

Globalクラスは、コンテナを作成するから派生しNinject.Web.NinjectHttpApplicationて実装する必要がCreateKernel()あります。

using Ninject; using Ninject.Web;

namespace Company.Web {
    public class Global : NinjectHttpApplication


        protected override IKernel CreateKernel()
        {
            IKernel kernel = new StandardKernel(new YourWebModule());
            return kernel;
        }

StandardKernelコンストラクタがかかりますModule

ステップ3-モジュール

この場合YourWebModule、モジュールは、Webアプリケーションが必要とするすべてのバインディングを定義します。

using Ninject;
using Ninject.Web;

namespace Company.Web
{
    public class YourWebModule : Ninject.Modules.NinjectModule
    {

        public override void Load()
        {
            Bind<ICustomerRepository>().To<CustomerRepository>();
        }   

この例では、ICustomerRepositoryインターフェースが参照CustomerRepositoryされる場合は常に、コンクリートが使用されます。

ステップ4-ページ

それが完了すると、各ページはから継承する必要がありますNinject.Web.PageBase

  using Ninject;
    using Ninject.Web;
    namespace Company.Web
    {
        public partial class Default : PageBase
        {
            [Inject]
            public ICustomerRepository CustomerRepo { get; set; }

            protected void Page_Load(object sender, EventArgs e)
            {
                Customer customer = CustomerRepo.GetCustomerFor(int customerID);
            }

InjectAttribute -[Inject]-注入するNinjectを伝えICustomerRepositoryCustomerRepoプロパティに。

すでにベースページがある場合は、ベースページをNinject.Web.PageBaseから派生させる必要があります。

ステップ5-マスターページ

必然的に、マスターページがあり、MasterPageが挿入されたオブジェクトにアクセスできるようにするには、マスターページを次の場所から派生させる必要がありますNinject.Web.MasterPageBase

using Ninject;
using Ninject.Web;

namespace Company.Web
{
    public partial class Site : MasterPageBase
    {

        #region Properties

        [Inject]
        public IInventoryRepository InventoryRepo { get; set; }     

ステップ6-静的Webサービスメソッド

次の問題は、静的メソッドに注入できないことでした。明らかに静的なAjaxPageMethodがいくつかあったので、メソッドを標準のWebサービスに移動する必要がありました。繰り返しますが、WebサービスはNinjectクラスから派生する必要があります- Ninject.Web.WebServiceBase

using Ninject;
using Ninject.Web;    
namespace Company.Web.Services
{

    [WebService(Namespace = "//tempuri.org/">http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]    
    [System.Web.Script.Services.ScriptService]
    public class YourWebService : WebServiceBase
    {

        #region Properties

        [Inject]
        public ICountbackRepository CountbackRepo { get; set; }

        #endregion

        [WebMethod]
        public Productivity GetProductivity(int userID)
        {
            CountbackService _countbackService =
                new CountbackService(CountbackRepo, ListRepo, LoggerRepo);

JavaScriptCompany.Web.Services.YourWebService.GetProductivity(user, onSuccess)では、ではなく標準サービスを参照する必要がありますPageMethods.GetProductivity(user, onSuccess)

私が見つけた他の唯一の問題は、ユーザーコントロールにオブジェクトを挿入することでした。Ninject機能を使用して独自のベースUserControlを作成することは可能ですが、必要なオブジェクトのユーザーコントロールにプロパティを追加し、コンテナページでプロパティを設定する方が簡単であることがわかりました。箱から出してUserControlsをサポートすることは、Ninjectの「やること」リストにあると思います。

Ninjectの追加は非常に簡単で、雄弁なIoCソリューションです。Xml構成がないため、多くの人が気に入っています。Ninject構文だけでオブジェクトをシングルトンに変換するなどの他の便利な「トリック」があります- Bind<ILogger>().To<WebLogger>().InSingletonScope()。WebLoggerを実際のシングルトン実装に変更する必要はありません。私はこれが好きです。


1
これはうまくいきますが、(テンプレートからの)新しいWebFormsアプリでこれを試したところ、Global.asax.csファイルにデフォルトのセッションメソッド(Application_Startなど)が含まれていると、アプリが不可解なエラーを返すことがわかりました。これらを削除する必要があることは明らかかもしれませんが(NinjectHttpApplicationに実装されているため)、それは私を捕らえました。
マット

お役に立ててうれしいです。エラーは奇妙に聞こえますが、例外は何でしたか?Application_Startにコードがあり、正常に動作します。
ジョーラッツァー2011年

3
Global.asax.csファイルのApplication_StartメソッドからスーパータイプのメソッドNinjectHttpApplication.Application_Startを呼び出すのを忘れました。私がそれをするとき、そうでなければそれは壊れました。
マット

1
絶対に、私が現在取り組んでいるアプリケーションにはベースページがあります(常に良い考えです)。ベースページを取得してPageBaseを実装するだけです。
ジョーラッツァー2011

2
これは今では時代遅れのようです。NuGetパッケージninject.webには、アプリをブートストラップするためのコードが含まれているため、NinjectHttpApplicationから直接継承する必要はありませんか?
RyanW 2012

68

Ninject v3.0のリリース(2012年4月12日現在)により、より簡単になりました。インジェクションはHttpModuleを介して実装されるため、ページをカスタムページ/マスターページから継承する必要はありません。クイックスパイクの手順(およびコード)は次のとおりです。

  1. 新しいASP.NETWebFormsプロジェクトを作成します
  2. NuGetを使用してNinject.Webライブラリを追加します(これにより、Ninject.Web.CommonライブラリとNinjectライブラリもダウンします)
  3. App_Start / NinjectWebCommon.cs / RegisterServicesメソッドにカスタムバインディングを登録します
  4. ページで属性インジェクションを使用する

NinjectWebCommon / RegisterServices

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IAmAModel>().To<Model1>();
    } 

デフォルト

public partial class _Default : System.Web.UI.Page
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine(Model.ExecuteOperation());
    }
}

Site.Master

public partial class SiteMaster : System.Web.UI.MasterPage
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine("From master: " 
            + Model.ExecuteOperation());
    }
}

モデル

public interface IAmAModel
{
    string ExecuteOperation();         
}

public class Model1 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 1";
    }
}

public class Model2 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 2";
    }
}

出力ウィンドウからの結果

I am a model 1
From master: I am a model 1

こんにちはジェイソン...私はそれを実装しようとしています... NuGetからNinject.Webライブラリを取得しました... App_Startにブートストラップを作成しました...デバッグするためにRegisterServicesにブレークポイントを追加しようとしましたが、そこに到達しません...何か他のものを追加することになっていますか?
ポール

1
@Paul Debugger.Break()をRegisterServicesメソッドに入れて、デバッグを開始できます。
ボギン2012

5
こんにちはジェイソン。これを機能させるのに問題があるので、これが完全な要約であるかどうか疑問に思いましたか?NinjectHttpModuleが実行時にロードされていることがわかりますが、インジェクションは発生していません。これが当てはまる理由を思いつくことができますか?
rusmus 2013年

3
素晴らしい例ありがとうそれはページ/マスターページでは機能しますが、Asmxでは機能しません。Asmxで動作させるにはどうすればよいですか?ありがとう。
lawphotog 2014

1
@mreyerosは、あなたが持っていることを確認しますNinjectWeb.csApp_Start。Ninjectを初期化するためのコードは、このファイルに含める必要があります。別のファイルにある場合(たとえばNinjectWebCommon.cs、機能しません)。これは、NuGetを使用して他のNinjectパッケージよりも後でNinject.Webをインストールした場合に発生する可能性があります。
nebffa 2014年

12

未解決のバグのため、ここでの回答は現在機能しません。これは、顧客のhttpmoduleを使用して、ninjectクラスから継承せずにページとコントロールに挿入する、@ Jasonの手順の修正バージョンです。

  1. 新しいASP.NETWebFormsプロジェクトを作成します
  2. NuGetを使用してNinject.Webライブラリを追加します
  3. App_Start / NinjectWebCommon.cs / RegisterServicesメソッドにカスタムバインディングを登録します
  4. InjectPageModuleを追加し、NinjectWebCommonに登録します
  5. ページで属性インジェクションを使用する

InjectPageModule.cs

 public class InjectPageModule : DisposableObject, IHttpModule
{
    public InjectPageModule(Func<IKernel> lazyKernel)
    {
        this.lazyKernel = lazyKernel;
    }

    public void Init(HttpApplication context)
    {
        this.lazyKernel().Inject(context);
        context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
    }

    private void OnPreRequestHandlerExecute(object sender, EventArgs e)
    {
        var currentPage = HttpContext.Current.Handler as Page;
        if (currentPage != null)
        {
            currentPage.InitComplete += OnPageInitComplete;
        }
    }

    private void OnPageInitComplete(object sender, EventArgs e)
    {
        var currentPage = (Page)sender;
        this.lazyKernel().Inject(currentPage);
        this.lazyKernel().Inject(currentPage.Master);
        foreach (Control c in GetControlTree(currentPage))
        {
            this.lazyKernel().Inject(c);
        }

    }

    private IEnumerable<Control> GetControlTree(Control root)
    {
        foreach (Control child in root.Controls)
        {
            yield return child;
            foreach (Control c in GetControlTree(child))
            {
                yield return c;
            }
        }
    }

    private readonly Func<IKernel> lazyKernel;
}

NinjectWebCommon / RegisterServices

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IHttpModule>().To<InjectPageModule>();
        kernel.Bind<IAmAModel>().To<Model1>();

    } 

デフォルト

public partial class _Default : System.Web.UI.Page
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine(Model.ExecuteOperation());
    }
}

Site.Master

public partial class SiteMaster : System.Web.UI.MasterPage
{

    [Inject]
    public IAmAModel Model { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Trace.WriteLine("From master: " 
            + Model.ExecuteOperation());
    }
}

モデル

public interface IAmAModel
{
    string ExecuteOperation();         
}

public class Model1 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 1";
    }
}

public class Model2 : IAmAModel
{
    public string ExecuteOperation()
    {
        return "I am a model 2";
    }
}

出力ウィンドウからの結果

I am a model 1
From master: I am a model 1

4
マスターページがないページでは失敗することに注意してください。これでNinjectWebCommonを変更しました: if (currentPage.Master!=null) { this.lazyKernel().Inject(currentPage.Master); }
H.Wolper 2015年

1
これを文書化するために時間を割いていただきありがとうございます。従来のWebフォームプロジェクトで同じ問題が発生しました。おかげさまで、これを並べ替えることができました。呼び出しが遅すぎたため、Page_Initの前に動作するように調整されましたが、それ以外は完璧です。ありがとう@アダム!
PoorbandTony 2016

この解決策は私にとって本当にランダムな問題を引き起こしました。たとえば、OnCommandイベントはRepeater内のLinkBut​​tonで実行を停止しました。ただし、すべてのコードビハインドイベントが中断されるわけではありません。
マイクコール

8

ASP.NETWebフォームにNinject.Webを実装する手順は次のとおりです。

  1. Global.asaxでNinjectHttpApplicationを実装します。カーネルの場合は、NinjectModuleを実装して渡します。
  2. コードビハインドでの各Webフォームページ読み込みイベントで、Ninject.Web.PageBaseを実装します。その上に[Inject]フィルターを使用してインスタンスクラスを追加します。

より詳細な例については、以下に私が見つけたいくつかの便利なリンクがあります。

1. http://joeandcode.net/post/Ninject-2-with-WebForms-35

2. http://davidhayden.com/blog/dave/archive/2008/06/20/NinjectDependencyInjectionASPNETWebPagesSample.aspx


1
これは、Ninject.Web拡張機能が追加されていることを前提としています。これは、まさに必要なことです。
Dave Thieben 2011

7
@nellbryantこれらのリンクは両方とも無効になっています。
ボギン2012

joeandcode.netリンクが無効になりました。アーカイブ版はこちら:web.archive.org/web/20160324142135/http
Chris Walsh

4

Ninject.Web拡張機能をご覧ください。基本インフラストラクチャを提供します https://github.com/ninject/ninject.web


5
例を挙げてリードする必要があることはわかっていますが、READMEは0バイトを超える必要があります。
Ruben Bartelink 2011

@Ruben:docuの更新は、リストatmの優先度の高いタスクの1つであることに同意します。
レモグローア2011

2
優先順位と、コミュニティからどれだけの支援が得られるかがすべてです。昨年、多くのドキュメントが追加されました。Ninject.Webは、他の機能よりも重要性が低いと考えているため、対象外です。a)WebFormsは廃止されました。代わりにMVCを使用してください。b)この拡張機能を作成していません。他のみんなと同じように、私はコードからこの拡張機能についての知識を得る必要があります。c)私はそれを自分で使用しません-私よりもはるかに優れたドキュメントを書くことができる他の人がいます。しかし、それはそれらのいずれにとっても重要ではないようです。私の暇な時間はあなたのように限られているので、私はすべてをすることはできません。
Remo Gloor 2012

6
@RyanWドキュメントが不足しているという理由だけで反対票を投じても、私のモチベーションが向上したり、このドキュメントを作成する優先度が高くなったりすることはありません。
Remo Gloor 2012

1
@RyanWどこでアイデアを得ますか?一年前からの卑劣なコメントには気分が悪いが、a)賛成票を伴っていたb)皮肉であったが、泣き言ではなかった。おもちゃを捨てるよりもレモがする完全に正当な点に反論してください。ところで、Unityには素晴らしいドキュメントがあり、あなたの路地にもっとあるかもしれません。そして、nellbryantまたはJor Rの答えを見て、それの誤りを見つけるか、それを使用してreadmeまたはサンプルを自分で作成してみてください。
Ruben Bartelink 2012

0

Steve Sanderson(Apress)による本「ProASP.NET MVC 2 Framework、2ndEdition」を確認してください。著者はNinjectを使用してデータベースに接続します。例を使用して、ニーズに合わせて調整できると思います。


はい、私はその質問をするきっかけとなったものを持っています。WebアプリケーションがWebフォームの場合、どのように行われますか?
nellbryant 2011

これは、私がWebFormsで通常行う方法でもあります。秘訣は、カーネルのGetメソッドを使用する必要があることです。
Didaxis 2011年

0
public IGoalsService_CRUD _context { get; set; }

_contextオブジェクトが何らかの理由でnullに設定されています。残りの設定は次のとおりです

public partial class CreateGoal : Page
{
    [Inject]
    public IGoalsService_CRUD _context { get; set; }
}

グローバルファイルの場合

protected override IKernel CreateKernel()
{
    IKernel kernel = new StandardKernel(new Bindings());
    return kernel;
}

public class Bindings : NinjectModule
{
    public override void Load()
    {
        Bind<goalsetterEntities>().To<goalsetterEntities>();
        Bind<IGoalsService_CRUD>().To<GoalsService_CRUD>();
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.