Meneruskan data ke Master Page di ASP.NET MVC

102

Apa cara Anda mengirimkan data ke Halaman Master (menggunakan ASP.NET MVC) tanpa melanggar aturan MVC?

Secara pribadi, saya lebih suka kode pengontrol abstrak (pengontrol dasar) atau kelas dasar yang diteruskan ke semua tampilan.

Łukasz Sowa
sumber
1
Saya menulis panduan tentang bagaimana saya mengelola ini: britishdeveloper.co.uk/2010/06/… harus membantu
BritishDeveloper

Jawaban:

77

Jika Anda lebih suka tampilan Anda memiliki kelas data tampilan yang diketik dengan kuat, ini mungkin berhasil untuk Anda. Solusi lain mungkin lebih tepat tetapi ini adalah keseimbangan yang bagus antara desain dan kepraktisan IMHO.

Halaman master mengambil kelas data tampilan yang diketik dengan kuat yang hanya berisi informasi yang relevan dengannya:

public class MasterViewData
{
    public ICollection<string> Navigation { get; set; }
}

Setiap tampilan yang menggunakan halaman master tersebut mengambil kelas data tampilan yang diketik dengan kuat yang berisi informasinya dan berasal dari data tampilan halaman master:

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
}

Karena saya tidak ingin pengontrol individu mengetahui apa pun tentang mengumpulkan data halaman master, saya merangkum logika itu ke dalam pabrik yang diteruskan ke setiap pengontrol:

public interface IViewDataFactory
{
    T Create<T>()
        where T : MasterViewData, new()
}

public class ProductController : Controller
{
    public ProductController(IViewDataFactory viewDataFactory)
    ...

    public ActionResult Index()
    {
        var viewData = viewDataFactory.Create<ProductViewData>();

        viewData.Name = "My product";
        viewData.Price = 9.95;

        return View("Index", viewData);
    }
}

Warisan cocok dengan master untuk melihat hubungan dengan baik, tetapi ketika harus membuat sebagian / kontrol pengguna saya akan menyusun data tampilan mereka ke dalam data tampilan halaman, misalnya

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
    public SubViewData SubViewData { get; set; }
}

<% Html.RenderPartial("Sub", Model.SubViewData); %>

Ini hanya contoh kode dan tidak dimaksudkan untuk dikompilasi sebagaimana adanya. Dirancang untuk ASP.Net MVC 1.0.

Kesalahan Umum
sumber
4
Ini adalah metode yang direkomendasikan oleh Scott Gutherie, jadi saya setuju.
Simon Fox
@Simon Fox - punya link ke rekomendasi scottgu? Tidak dapat menemukannya.
orip
Maaf. Mengalami sedikit kesulitan memahami bagian ini. Konstruktor untuk pengontrol melewati turunan IViewDataFactory tetapi sistem mengharapkan konstruktor tanpa parameter. Saya juga tidak terbiasa dengan sintaks C # (khususnya "MasterViewData, new ()") untuk antarmuka. Adakah yang bisa menjelaskan atau mengarahkan saya ke sumber yang bagus. Terima kasih.
Jason
5
Saya suka memiliki model yang diketik dengan kuat untuk dikerjakan, tetapi saya bukan penggemar berat menggabungkan data master dengan semua model dan tindakan saya yang lain. Melompat ke utas ini agak terlambat, tetapi saya memposting pendekatan saya ke data master yang membuat segalanya lebih longgar.
Todd Menier
59

Saya lebih suka memecah potongan data-driven dari tampilan master menjadi sebagian dan merendernya menggunakan Html.RenderAction . Ini memiliki beberapa keunggulan berbeda dibandingkan pendekatan pewarisan model tampilan populer:

  1. Data tampilan master sepenuhnya dipisahkan dari model tampilan "biasa". Ini adalah komposisi yang melebihi pewarisan dan menghasilkan sistem yang lebih longgar yang lebih mudah diubah.
  2. Model tampilan master dibuat oleh tindakan pengontrol yang sepenuhnya terpisah. Tindakan "biasa" tidak perlu mengkhawatirkan hal ini, dan tidak perlu pabrik data tampilan, yang tampaknya terlalu rumit untuk selera saya.
  3. Jika Anda kebetulan menggunakan alat seperti AutoMapper untuk memetakan domain Anda ke model tampilan Anda, Anda akan merasa lebih mudah untuk mengonfigurasi karena model tampilan Anda akan lebih mirip dengan model domain Anda ketika mereka tidak mewarisi data tampilan master.
  4. Dengan metode tindakan terpisah untuk data master, Anda dapat dengan mudah menerapkan cache keluaran ke wilayah halaman tertentu. Biasanya tampilan master berisi data yang lebih jarang berubah daripada konten halaman utama.
Todd Menier
sumber
3
+1. Keuntungan lainnya adalah Anda dapat memiliki tampilan yang sama menggunakan halaman master yang berbeda bergantung pada status waktu proses saat ini.
StriplingWarrior
1
Saya sangat menyukai jawaban ini - pendekatan lain yang diuraikan tampaknya agak terlalu rumit.
Paddy
2
Ini solusi paling elegan menurut saya.
autonomatt
1
Solusi ini tampaknya yang terbaik bagi saya juga. Terima kasih banyak!
JimDaniel
1
Ini adalah cara yang bagus, tapi ingat bahwa Anda masih harus menentukan rute ke "tindakan parsial" Anda. Lihat jawaban ini stackoverflow.com/a/3553617/56621
Alex
20

EDIT

Generic Error telah memberikan jawaban yang lebih baik di bawah ini. Mohon dibaca!

Jawaban Asli

Microsoft sebenarnya telah memposting entri tentang cara "resmi" untuk menangani ini. Ini memberikan panduan langkah demi langkah dengan penjelasan tentang alasan mereka.

Singkatnya, mereka merekomendasikan menggunakan kelas pengontrol abstrak, tetapi buktikan sendiri.

Michael La Voie
sumber
TERIMA KASIH! Contoh tersebut adalah PERSIS apa yang saya lakukan ... kategori pada setiap halaman yang berasal dari database.
Martin
Scott Gutherie, salah satu penulis MVC merekomendasikan solusi yang diberikan oleh @Generic Error di bawah ini
Simon Fox
1
+1 untuk mengarahkan ke jawaban terbaik meskipun jawaban Anda secara resmi benar dan diterima sebagai jawaban oleh OP.
IsmailS
+1 untuk mengarahkan ke jawaban terbaik meskipun jawaban Anda secara resmi benar dan diterima sebagai jawaban oleh OP.
Dave Jellison
Sebenarnya, Todd Menier's saat ini adalah jawaban terbaik untuk ini.
andreialecu
7

Pengontrol abstrak adalah ide yang bagus, dan saya belum menemukan cara yang lebih baik. Saya juga tertarik untuk melihat apa yang telah dilakukan orang lain.

Ian P
sumber
2

Saya menemukan bahwa orang tua yang sama untuk semua objek model yang Anda berikan ke tampilan sangat berguna.

Akan selalu cenderung ada beberapa properti model umum antar halaman.

Matt Mitchell
sumber
0

Objek Request.Params bisa berubah. Sangat mudah untuk menambahkan nilai skalar ke dalamnya sebagai bagian dari siklus pemrosesan permintaan. Dari perspektif tampilan, informasi itu bisa saja disediakan di QueryString atau FORM POST. hth


sumber
0

Saya berpendapat bahwa cara lain yang baik adalah membuat Antarmuka untuk tampilan dengan beberapa Properti seperti ParentView dari beberapa antarmuka, sehingga Anda dapat menggunakannya baik untuk kontrol yang memerlukan referensi ke halaman (kontrol orang tua) dan untuk tampilan master yang harus diakses dari tampilan.

dimarzionis
sumber
0

Solusi lainnya kurang elegan dan memakan waktu terlalu lama. Saya minta maaf karena melakukan hal yang sangat menyedihkan dan miskin ini hampir setahun kemudian:

<script runat="server" type="text/C#">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        MasterModel = SiteMasterViewData.Get(this.Context);
    }

    protected SiteMasterViewData MasterModel;
</script>

Jadi jelas saya memiliki metode statis Get () di SiteMasterViewData yang mengembalikan SiteMasterViewData.

rasx
sumber
bagi banyak orang ini mungkin tampak agak hacky atau 'najis' tetapi menyelesaikan pekerjaan dengan cepat
argh
Ugh. Kode Anda tampaknya jauh lebih sulit untuk dipertahankan jika Anda telah menggunakan Html.RenderAction ().
Dan Esparza