2016-08-02 10 views
1

私はベースコントローラを読んできましたが、私はそのコンセプトを理解できないようです。私は何もコードを繰り返さないので、コントローラのコードを単純化する必要があります。データベースを使用してWebサイトのデータを収集し、ビューで使用するいくつかのリストを作成します。すべてのページは、ベースコントローラーでコピーした2つのリストを共有します。私がpagescontrollerのリストを削除すると、現在のコンテキストに「スライダ」と「パーテナイア」という名前が存在しないというエラーが表示されます。繰り返しコードを防止する最善の方法は何でしょうか?ベースコントローラまたは共有リソースにアクセスするためのメソッド

これは私のベースのコントローラです:

public class BaseController : Controller 
{ 
    PIAEntities db = new PIAEntities(); 

    public BaseController() 
    { 
     var sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     var partenaires = db.Partenaire.Where(p => p.Afficher); 
    } 
} 

そして、これはすべての私のページ

public class PagesController : BaseController 
{ 
    public PagesController() : base() 
    { 

    } 

    PIAEntities db = new PIAEntities(); 

    public ActionResult Activités() 
    { 
     var sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     var partenaires = db.Partenaire.Where(p => p.Afficher); 
     var model = new ModelDeBase { Slider = sliders, Partenaire = partenaires }; 

     return View(model); 
    } 

    public ActionResult Actualités() 
    { 
     var sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     var pageActualites = db.Actualite.OrderByDescending(a => a.Date_publication).Take(10); 
     var donateurs = db.Donateur.Where(d => d.Afficher); 
     var partenaires = db.Partenaire.Where(p => p.Afficher); 
     var model = new ModelActualite { Slider = sliders, Partenaire = partenaires, PageActualite = pageActualites, Donateur = donateurs }; 

     return View(model); 
    } 
} 

ソリューションを管理するコントローラの一部です:

[OK]を、今では動作し、私は私のベースコントローラでこれを使用して終了しました

public class BaseController : Controller 
{ 
    PIAEntities db = new PIAEntities(); 
    protected IEnumerable<Actualite> sliders { get; private set; } 
    protected IEnumerable<Partenaire> partenaires { get; private set; } 

    public BaseController() 
    { 
     sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     partenaires = db.Partenaire.Where(p => p.Afficher); 
    } 
} 

とページコントローラ:あなたの現在のコードで

public class PagesController : BaseController 
{ 
    public PagesController() : base() 
    { 

    } 

    PIAEntities db = new PIAEntities(); 

    public ActionResult Activités() 
    { 
     var model = new ModelDeBase { Slider = sliders, Partenaire = partenaires }; 

     return View(model); 
    } 

    public ActionResult Actualités() 
    { 
     var pageActualites = db.Actualite.OrderByDescending(a => a.Date_publication).Take(10); 
     var donateurs = db.Donateur.Where(d => d.Afficher); 
     var model = new ModelActualite { Slider = sliders, Partenaire = partenaires, PageActualite = pageActualites, Donateur = donateurs }; 

     return View(model); 
    } 
} 
+2

あなたは、C#での継承を検討する必要がありますhttps://msdn.microsoft.com/en-us/library/ms173149.aspx – blins

答えて

1

から、これらのフィールドにアクセスすることができるはず

this._sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 

子クラスがこれらのプロパティを変更できないように、暗黙的にprivateセッターとしてクラスレベルで宣言する必要があります。

public class BaseController : Controller 
{ 
    PIAEntities db = new PIAEntities(); 

    protected IEnumerable<Actualite> sliders { get; private set; } 

    protected IEnumerable<Paternaire> partenaires { get; private set; } 

    public BaseController() 
    { 
     this.sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     this.partenaires = db.Partenaire.Where(p => p.Afficher); 
    } 
} 
+0

私はそれらを保護して設定するとエラーが発生します:このcontectでは使用できません設定されたアクセサーにアクセスできないので –

+0

私はアクセスを妨げていた私的なセットではありませんでした。 –

+0

@SteveMorin - 値を正しく取得できるはずです。プライベートアクセサのために 'set'できないでしょう。それは一般的に相続財産で良いことです。しかし、あなたの子クラスがこれらの値を変更する必要がある場合は、プライベートアクセサを削除することができます。 :) – Yogi

1

、あなたはActualiteのBaseControllerのコンストラクタでPartenaireのを追加し、PagesControllerは、その継承される照会されています。しかし、あなたの活動アクション・メソッドでは、同じデータを再度照会しています!ユーザがPages/Activitesを要求すると、BaseControllerコンストラクタコードとアクティビティコントローラ内のコードが実行されます。だからあなたはそこにコードを複製している。また、BaseControllerコンストラクタで照会しているデータは、(メソッドのローカルスコープを持つ)変数を設定しており、他の場所では使用されていません。あなたができることの1つは、いくつかの保護された変数を保持し、それに割り当てることです。 子クラスのこれらの保護された変数にアクセスできます。あなたのPageControllerで今すぐ

public class BaseController : Controller 
{ 
    protected List<Actualite> Actualities {set;get;} 
    PIAEntities db = new PIAEntities(); 

    public BaseController() 
    { 
     this.Actualities = db.Actualite.Where(a => a.Afficher) 
          .OrderByDescending(a => a.Date_publication).ToList();    
    } 
} 

、あなたは単にユーザー this.Actualitesことがあります。再度照会する必要はありません。

public ActionResult Activités() 
{ 
    var model = new ModelDeBase { Slider = this.Actualities }; 
    return View(model); 
} 

他のコレクションでも同じことができます。

コンストラクタ内にそのコードがあるので、BaseControllerから継承するすべてのコントローラへの呼び出しが呼び出されます。しかし、あなたのアクションメソッドのいくつかは、このデータを必要としないかもしれません(しかし、他のベースコントローラー変数/メソッドを依然として使用したい)。その場合は、サービスクラスに移動し、と呼びます(必要に応じて)。お使いのコントローラで今

public class PageService 
{ 
    public IEnumerable<Actualite> GetActualites() 
    { 
    return db.Actualite.Where(a => a.Afficher) 
           .OrderByDescending(a => a.Date_publication).ToList(); 
    } 
} 

、あなたはこののオブジェクトを作成し、必要に応じてGetActualitesメソッドを呼び出します。

public ActionResult Activités() 
{ 
    var s=new PageService(); 
    var model = new ModelDeBase { Slider =s.GetActualites()}; 
    return View(model); 
} 

さらに進んで、インターフェイスを抽出し、依存性注入フレームワークを使用して具体的な実装を注入することができます。これはコントローラの単体テストに役立ちます。

+0

サービスクラスは非常に興味深いされていること。特定のページのみに固有のリストごとにこれを使用するのが最善でしょうか? –

+1

データのサービスクラスを作成します。たとえば、製品に関するデータを取得する場合などです。 ProductServiceクラスを作成します。テスト可能なコントローラを書くことに興味がある場合は、そのサービスクラス用のインターフェイスを作成して使用する必要があります。ここでそれについての記事は、http://stackoverflow.com/questions/36389525/how-to-implement-dependency-injection-in-mvc – Shyju

2

現在、コンストラクタのスコープ内のオブジェクトのみを宣言しているため、このエラーが発生しています。修正するには、それらをコンストラクタの外で宣言し、コンストラクタ内の値を設定します(タイプが正しいかどうかはわかりませんが、あなたの例からそれらを差し引かなければなりません)。あなたがアクセスできるようになります今

public class BaseController : Controller 
{ 
    PIAEntities db = new PIAEntities(); 

    // Fields added 
    protected IQueryable<Partenaire> partenaires ; 
    protected IQueryable<Actualite> sliders ; 

    public BaseController() 
    { 

     sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     partenaires = db.Partenaire.Where(p => p.Afficher); 
    } 
} 

public class BaseController : Controller 
{ 
    PIAEntities db = new PIAEntities(); 
    IQueryable<Actualite> sliders; 
    IQueryable<Paternaire> partenaires; 

    public BaseController() 
    { 
     sliders = db.Actualite.Where(a => a.Afficher).OrderByDescending(a => a.Date_publication); 
     partenaires = db.Partenaire.Where(p => p.Afficher); 
    } 
} 
0

あなたがそれらをベースコントローラ内のフィールドまたはプロパティにする必要があり、現在、あなたは、コンストラクタ内のローカル変数を持っている、ようにそれがために変更このベースコントローラから継承する他のコントローラ。

0

スライダーの値を保持するために、基本コントローラーにいくつかのフィールドを追加します。&パーティション。これらをコンストラクタで設定することができます。あなたは、あなたのvaraiblesの両方がslidersをIEとpartenairesBaseControllerコンストラクタのスコープで宣言されているので、彼らは、コンストラクタの外にアクセスできません派生コントローラ

関連する問題