Meneruskan data ke tata letak yang umum untuk semua halaman

124

Saya memiliki situs web yang memiliki halaman tata letak. Namun halaman tata letak ini memiliki data yang semua model halaman harus memberikan judul halaman, nama halaman dan lokasi di mana kita sebenarnya untuk pembantu HTML yang saya lakukan yang melakukan beberapa tindakan. Juga setiap halaman memiliki properti model tampilan mereka sendiri.

Bagaimana saya bisa melakukan ini? Tampaknya itu ide yang buruk untuk mengetik tata letak tapi bagaimana cara menyampaikan info ini?

Rushino
sumber
10
Untuk siapa pun yang membaca balasan di sini, silakan lihat stackoverflow.com/a/21130867/706346 di mana Anda akan melihat solusi yang jauh lebih sederhana dan lebih rapi daripada apa pun yang diposting di sini.
Avrohom Yisroel
5
@AvrohomYisroel saran bagus. Namun saya lebih suka pendekatan @Colin Bacon karena diketik kuat dan bukan di ViewBag. Mungkin masalah preferensi. Memberikan suara positif pada komentar Anda
JP Hellemons
untuk mvc 5 lihat jawaban ini: stackoverflow.com/a/46783375/5519026
Laz Ziya

Jawaban:

143

Jika Anda diminta untuk meneruskan properti yang sama ke setiap halaman, maka membuat model tampilan dasar yang digunakan oleh semua model tampilan Anda akan bijaksana. Halaman tata letak Anda kemudian dapat menggunakan model dasar ini.

Jika ada logika yang diperlukan di balik data ini, maka ini harus dimasukkan ke dalam pengontrol dasar yang digunakan oleh semua pengontrol Anda.

Ada banyak hal yang dapat Anda lakukan, pendekatan yang penting adalah tidak mengulangi kode yang sama di banyak tempat.

Edit: Perbarui dari komentar di bawah

Berikut adalah contoh sederhana untuk mendemonstrasikan konsep tersebut.

Buat model tampilan dasar yang akan mewarisi semua model tampilan.

public abstract class ViewModelBase
{
    public string Name { get; set; }
}

public class HomeViewModel : ViewModelBase
{
}

Halaman tata letak Anda dapat menganggap ini sebagai modelnya.

@model ViewModelBase
<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Test</title>
    </head>
    <body>
        <header>
            Hello @Model.Name
        </header>
        <div>
            @this.RenderBody()
        </div>
    </body>
</html>

Terakhir, atur data dalam metode tindakan.

public class HomeController
{
    public ActionResult Index()
    {
        return this.View(new HomeViewModel { Name = "Bacon" });
    }
}
Colin Bacon
sumber
12
Tetapi data digunakan dalam tata letak. Bagaimana saya bisa meneruskan data ke tata letak?
Rushino
2
Sempurna! Saya melihat kesalahan saya. Saya lupa untuk memberikan model ke tampilan .. kesalahan yang timpang. Terima kasih!
Rushino
7
Masalah dengan pendekatan ini adalah terkadang tidak setiap tampilan memiliki ViewModel, jadi ini tidak akan berfungsi dalam kasus tersebut: O /
Cacho Santa
16
Tetapi bukankah ini mengharuskan setiap pengontrol dan setiap tindakan menyertakan kode {Name = "Bacon"}? Dan jika saya ingin menambahkan properti lain ke ViewModelBase, saya harus pergi ke setiap pengontrol dan setiap tindakan dan menambahkan kode untuk mengisi properti itu? Anda menyebutkan "Jika ada logika yang diperlukan [...] ini harus dimasukkan ke dalam pengontrol dasar [...]". Bagaimana ini akan bekerja untuk menghilangkan kode berulang ini di setiap pengontrol dan setiap tindakan?
Lee
5
@Lee Jika ini adalah data umum di semua halaman, pengontrol dasar adalah tempat Anda meletakkan ini. Pengontrol Anda kemudian mewarisi dari pengontrol dasar ini. mis public class HomeController : BaseController. Dengan cara ini kode umum hanya perlu ditulis sekali dan dapat diterapkan ke semua pengontrol.
Colin Bacon
73

Saya menggunakan pembantu html RenderAction untuk pisau cukur dalam tata letak.

@{
   Html.RenderAction("Action", "Controller");
 }

Saya membutuhkannya untuk string sederhana. Jadi tindakan saya mengembalikan string dan menuliskannya dengan mudah. Tetapi jika Anda membutuhkan data yang kompleks, Anda dapat mengembalikan PartialViewResult dan model.

 public PartialViewResult Action()
    {
        var model = someList;
        return PartialView("~/Views/Shared/_maPartialView.cshtml", model);
    }

Anda hanya perlu meletakkan model Anda di awal tampilan parsial '_maP PartialView.cshtml' yang Anda buat

@model List<WhatEverYourObjeIs>

Kemudian Anda dapat menggunakan data dalam model dalam tampilan parsial itu dengan html.

Burk
sumber
18
Sejauh ini, ini adalah jawaban terbaik!
gingerbreadboy
@gingerbreadboy setuju itu mempromosikan enkapsulasi yang baik dan pemisahan perhatian.
A-Dubb
35

Pilihan lainnya adalah membuat kelas LayoutModel terpisah dengan semua properti yang Anda perlukan dalam layout, dan kemudian memasukkan instance kelas ini ke dalam ViewBag. Saya menggunakan metode Controller.OnActionExecuting untuk mengisinya. Kemudian, di awal tata letak, Anda dapat menarik objek ini kembali dari ViewBag dan terus mengakses objek yang sangat diketik ini.

DenNukem
sumber
1
Ini sebenarnya terdengar seperti solusi yang paling tidak menyakitkan, apakah ada kerugiannya? +1
formatc
2
Jelas merupakan solusi terbaik dan saya tidak melihat adanya kerugian.
Wiktor Zychla
7
Saya tidak melihat apa yang diberikan ini kepada Anda. Jika Anda memiliki kelas dengan semua properti yang Anda butuhkan untuk tata letak, mengapa repot-repot menambahkannya ke ViewBag hanya untuk membuangnya kembali? Gunakan model dalam tampilan tata letak, Anda masih dapat mengisi model OnActionExecuting. Menggunakan ViewBag juga berarti Anda kehilangan keamanan jenis pada pengontrol Anda, bukan hal yang baik.
Colin Bacon
3
Hal ini memberi saya kemampuan untuk menambahkan model untuk tata letak, tanpa harus merestrukturisasi semua model untuk mewarisi dari model "super" tunggal di semua metode semua pengontrol, dalam proyek yang sudah ada. Jika Anda memulai dari awal, Anda dapat memilih untuk menurunkan semua model Anda dari akar umum.
DenNukem
5
@ColinBacon Keuntungan lain dari opsi ini adalah Tindakan Anda tidak harus selalu memiliki model tampilan. Selain itu, saya berpendapat bahwa pengembang perlu mengetahui bahwa mereka harus selalu mewarisi model tampilan mereka dari basis adalah suatu kerugian.
Josh Noe
28

Agaknya, kasus penggunaan utama untuk ini adalah mendapatkan model dasar ke tampilan untuk semua (atau sebagian besar) tindakan pengontrol.

Mengingat itu, saya telah menggunakan kombinasi dari beberapa jawaban ini, dukungan piggy utama pada jawaban Colin Bacon.

Benar bahwa ini masih logika pengontrol karena kita sedang mengisi model tampilan untuk kembali ke tampilan. Jadi tempat yang tepat untuk meletakkan ini adalah di pengontrol.

Kami ingin ini terjadi pada semua pengontrol karena kami menggunakan ini untuk halaman tata letak. Saya menggunakannya untuk tampilan parsial yang dirender di halaman tata letak.

Kami juga masih menginginkan manfaat tambahan dari ViewModel yang diketik dengan kuat

Jadi, saya telah membuat BaseViewModel dan BaseController. Semua Pengontrol ViewModels masing-masing akan mewarisi dari BaseViewModel dan BaseController.

Kode:

BaseController

public class BaseController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var model = filterContext.Controller.ViewData.Model as BaseViewModel;

        model.AwesomeModelProperty = "Awesome Property Value";
        model.FooterModel = this.getFooterModel();
    }

    protected FooterModel getFooterModel()
    {
        FooterModel model = new FooterModel();
        model.FooterModelProperty = "OMG Becky!!! Another Awesome Property!";
    }
}

Perhatikan penggunaan OnActionExecuted seperti yang diambil dari posting SO ini

HomeController

public class HomeController : BaseController
{
    public ActionResult Index(string id)
    {
        HomeIndexModel model = new HomeIndexModel();

        // populate HomeIndexModel ...

        return View(model);
    }
}

BaseViewModel

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}

HomeViewModel

public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}

FooterModel

public class FooterModel
{
    public string FooterModelProperty { get; set; }
}

Layout.cshtml

@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>

_Nav.cshtml

@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>

Semoga ini membantu.

gerimis
sumber
2
Saya menggunakan pendekatan ini, tetapi lebih suka mewarisi dari antarmuka daripada kelas dasar. Jadi saya lakukan: var model = filterContext.Controller.ViewData.Model sebagai IBaseViewModel if (model! = Null) {model.AwesomeModelProperty = "Awesome Property Value"; }
Tom Gerken
2
jawaban yang bagus, saya lebih suka yang ini dari yang lainnya.
Jynn
1
Jawaban yang bagus, tapi saya punya pertanyaan. "Bagaimana jika saya memiliki beberapa tampilan yang tidak memiliki ViewModels ...?"
Isma Haro
Mencoba ini, tetapi pada Tindakan Indeks, OnActionExecuted mengisi FooterModel dan kemudian HomeIndexModel baru dibuat dengan FooterModel null :(
SteveCav
1
@drizzie: di pengontrol dasar Anda, model adalah variabel lokal dalam metode Filter: var model = filterContext.Controller.ViewData.Model sebagai BaseViewModel. Saya tidak mengerti bagaimana MVC memahami bahwa variabel lokal ini sama dengan model yang dikirim HomeController untuk dilihat.
Hooman Bahreini
9

Anda tidak perlu mengacaukan tindakan atau mengubah model, cukup gunakan pengontrol dasar dan transmisikan pengontrol yang ada dari tata letak konteks tampilan.

Buat pengontrol dasar dengan data umum yang diinginkan (judul / halaman / lokasi dll) dan inisialisasi tindakan ...

public abstract class _BaseController:Controller {
    public Int32 MyCommonValue { get; private set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {

        MyCommonValue = 12345;

        base.OnActionExecuting(filterContext);
    }
}

Pastikan setiap pengontrol menggunakan pengontrol dasar ...

public class UserController:_BaseController {...

Transmisikan pengontrol dasar yang ada dari konteks tampilan di _Layout.cshmlhalaman Anda ...

@{
    var myController = (_BaseController)ViewContext.Controller;
}

Sekarang Anda dapat merujuk ke nilai-nilai di pengontrol dasar dari halaman tata letak Anda.

@myController.MyCommonValue

MEMPERBARUI

Anda juga dapat membuat ekstensi halaman yang memungkinkan Anda untuk menggunakannya this.

//Allows typed "this.Controller()." in cshtml files
public static class MyPageExtensions {
    public static _BaseController Controller(this WebViewPage page) => Controller<_BaseController>(page);
    public static T Controller<T>(this WebViewPage page) where T : _BaseController => (T)page.ViewContext.Controller;
}

Maka Anda hanya perlu mengingat untuk menggunakan this.Controller()saat Anda menginginkan pengontrol.

@{
    var myController = this.Controller(); //_BaseController
}

atau pengontrol khusus yang mewarisi dari _BaseController...

@{
    var myController = this.Controller<MyControllerType>();
}
Carter Medlin
sumber
Apa yang setara dengan ini dalam inti .net? Karena ViewContext.Controller tidak ada dan ada beberapa perubahan dalam rantai warisan
Jayanth Thyagarajan
4

jika Anda ingin meneruskan seluruh model, lakukan seperti di layout:

@model ViewAsModelBase
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8"/>
    <link href="/img/phytech_icon.ico" rel="shortcut icon" type="image/x-icon" />
    <title>@ViewBag.Title</title>
    @RenderSection("styles", required: false)    
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    @RenderSection("scripts", required: false)
    @RenderSection("head", required: false)
</head>
<body>
    @Html.Action("_Header","Controller", new {model = Model})
    <section id="content">
        @RenderBody()
    </section>      
    @RenderSection("footer", required: false)
</body>
</html>

dan tambahkan ini di pengontrol:

public ActionResult _Header(ViewAsModelBase model)
Yakir Manor
sumber
4

Saya rasa tidak ada jawaban yang cukup fleksibel untuk aplikasi tingkat perusahaan besar. Saya bukan penggemar terlalu banyak menggunakan ViewBag, tetapi dalam kasus ini, untuk fleksibilitas, saya akan membuat pengecualian. Inilah yang akan saya lakukan ...

Anda harus memiliki pengontrol dasar di semua pengontrol Anda. Tambahkan data Layout Anda OnActionExecuting di pengontrol dasar Anda (atau OnActionExecuted jika Anda ingin menunda itu) ...

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext     
        filterContext)
    {
        ViewBag.LayoutViewModel = MyLayoutViewModel;
    }
}

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View(homeModel);
    }
}

Kemudian di _Layout.cshtml Anda, tarik ViewModel dari ViewBag ...

@{
  LayoutViewModel model = (LayoutViewModel)ViewBag.LayoutViewModel;
}

<h1>@model.Title</h1>

Atau...

<h1>@ViewBag.LayoutViewModel.Title</h1>

Melakukan ini tidak mengganggu pengkodean untuk pengontrol halaman atau model tampilan Anda.

Jack Sutherland
sumber
Saya suka ide Anda, tetapi bagaimana jika Anda memiliki yang MyLayoutViewModeldibuat secara dinamis, bagaimana saya dapat mengirimkan beberapa parameter ke OnActionExecutingmetode?
Rajmond Burgaj
1
Uh, Anda masih membutuhkan metode base.OnActionExecuting(filterContext)Anda OnActionExecuting!!!
ErikE
4

Membuat tampilan dasar yang mewakili model tampilan Tata Letak adalah pendekatan yang buruk. Bayangkan Anda ingin memiliki model yang mewakili navigasi yang ditentukan dalam tata letak. Maukah kamu melakukannyaCustomersViewModel : LayoutNavigationViewModel ? Mengapa? Mengapa Anda harus meneruskan data model navigasi melalui setiap model tampilan yang Anda miliki dalam solusi?

Model tampilan Tata Letak harus dikhususkan, dengan sendirinya dan tidak boleh memaksa model tampilan lainnya untuk bergantung padanya.

Sebagai gantinya, Anda dapat melakukan ini, di _Layout.cshtmlfile Anda :

@{ var model = DependencyResolver.Current.GetService<MyNamespace.LayoutViewModel>(); }

Yang terpenting, kami tidak perlu new LayoutViewModel()dan kami akan mendapatkan semua dependensi yang LayoutViewModeltelah diselesaikan untuk kami.

misalnya

public class LayoutViewModel
{
    private readonly DataContext dataContext;
    private readonly ApplicationUserManager userManager;

    public LayoutViewModel(DataContext dataContext, ApplicationUserManager userManager)
    {
    }
}
hyankov
sumber
Di mana Anda mengisi model ini? Di BaseController juga?
ndberg
Saya membayangkan ini akan menjadi ide yang baik untuk Scopedobjek model tata letak di ASP..Net Core juga.
James Wilkins
Saya tidak akan memiliki pandangan untuk mengambil ketergantungan. Itu jelas bukan "MVC". Service Locator adalah anti-pola .
Jiveman
Bertentangan dengan kepercayaan populer, Service Locator bukanlah anti-pola dan sebenarnya ini tidak ada hubungannya dengan MVC, apakah Anda hanya melempar kata-kata buzz @Jiveman? blog.gauffin.org/2012/09/service-locator-is-not-an-anti-pattern
hyankov
Poin utama Jgauffin dalam artikel itu tampaknya adalah bahwa istilah "anti-pola" tidak boleh diterapkan ke Service Locator, karena setidaknya ada beberapa penggunaan SL yang valid. Poin yang adil. Namun, seperti yang dibuktikan dalam beberapa komentar diskusinya sendiri, dia menyarankan bahwa meskipun SL mungkin merupakan pendekatan yang valid ketika membangun perpustakaan dan kerangka kerja, itu tidak selalu direkomendasikan ketika membangun aplikasi (yang saya anggap pertanyaan OP dan diskusi ini di sini menjadi berputar di sekitar).
Jiveman
3

Jawaban lain telah mencakup hampir semua hal tentang bagaimana kita dapat mengirimkan model ke halaman tata letak kita. Tetapi saya telah menemukan cara yang dapat digunakan untuk meneruskan variabel ke halaman tata letak Anda secara dinamis tanpa menggunakan model atau tampilan parsial dalam tata letak Anda. Katakanlah Anda memiliki model ini -

public class SubLocationsViewModel
{
    public string city { get; set; }
    public string state { get; set; }
}

Dan Anda ingin mendapatkan kota dan negara bagian secara dinamis. Misalnya

di index.cshtml Anda, Anda dapat meletakkan dua variabel ini di ViewBag

@model  MyProject.Models.ViewModel.SubLocationsViewModel
@{
    ViewBag.City = Model.city;
    ViewBag.State = Model.state;
}

Lalu di layout.cshtml Anda, Anda dapat mengakses variabel viewbag tersebut

<div class="text-wrap">
    <div class="heading">@ViewBag.City @ViewBag.State</div>
</div>
Chirag K
sumber
ini berfungsi dengan baik, @stun_Gravy apakah ada kegagalan menggunakan ViewBag untuk meneruskan data seperti peran atau tingkat akses pengguna?
3not3
3

Ada cara lain untuk menangani ini. Mungkin bukan cara terbersih dari sudut pandang arsitektural, tetapi ini menghindari banyak rasa sakit yang terkait dengan jawaban lain. Cukup masukkan layanan dalam tata letak Razor, lalu panggil metode yang mendapatkan data yang diperlukan:

@inject IService myService

Kemudian nanti di tampilan tata letak:

@if (await myService.GetBoolValue()) {
   // Good to go...
}

Sekali lagi, tidak bersih dalam hal arsitektur (jelas layanan tidak boleh disuntikkan langsung ke tampilan), tetapi itu menyelesaikan pekerjaan.

Andrew
sumber
Bukan cara terbersih? Saya tidak setuju. Saya rasa ini sebersih yang didapat: objek diteruskan dari tempat dibuat langsung ke tempat yang Anda inginkan, tanpa "mencemari" pengontrol lain dengan item yang tidak perlu mereka lihat. Menggunakan @injectadalah solusi terbaik, menurut saya.
dasblinkenlight
1
Memikirkan hal ini lebih mungkin Anda benar. Fakta bahwa metode ini menghindari begitu banyak rasa sakit adalah tanda bahwa mungkin ini cara terbersih. Saya telah mengerjakan aplikasi ASP.NET Core yang sangat besar dan saya menggunakan pola ini untuk hal-hal seperti logika breadcrumb navigasi, data header yang ada di sebagian besar halaman, hal-hal seperti itu. Saya telah menghindari begitu banyak rasa sakit dengan melakukannya dengan cara ini.
Andrew
2

Anda juga dapat menggunakan RenderSection , ini membantu Anda untuk memasukkan Modeldata Anda ke file_Layout tampilan.

Anda dapat menyuntikkan View ModelData, Json, Script, CSS,HTML dll

Dalam contoh ini saya menyuntikkan Jsondari IndexView saya keLayout View saya.

Index.chtml

@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }

_Layout.cshtml

@RenderSection("commonLayoutData", false)

Ini menghilangkan kebutuhan untuk membuat Basis terpisah View Model .

Harapan membantu seseorang.

shaijut
sumber
1
Solusi sempurna saat Anda hanya perlu merender sesuatu yang spesifik untuk beberapa tampilan.
Kunal
1

apa yang saya lakukan sangat sederhana dan berhasil

Deklarasikan properti Statis di pengontrol apa pun atau Anda dapat membuat kelas data dengan nilai statis jika Anda ingin seperti ini:

public static username = "Admin";
public static UserType = "Administrator";

Nilai-nilai ini dapat diperbarui oleh pengontrol berdasarkan operasi. nanti Anda dapat menggunakannya di _Layout Anda

Dalam _layout.cshtml

@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
Bisnis elektronik
sumber
1
Itu selalu membantu menambahkan beberapa penjelasan pada jawaban Anda, untuk membuatnya lebih jelas dan dapat dimengerti. Harap baca stackoverflow.com/help/how-to-answer .
32cupo
0

Mengapa tidak ada yang menyarankan metode ekstensi pada ViewData?

Pilihan 1

Menurut saya sejauh ini solusi yang paling tidak mengganggu dan paling sederhana untuk masalah ini. Tidak ada string hardcode. Tidak ada batasan yang diberlakukan. Tidak ada pengkodean ajaib. Tidak ada kode yang rumit.

public static class ViewDataExtensions
{
    private const string TitleData = "Title";
    public static void SetTitle<T>(this ViewDataDictionary<T> viewData, string value) => viewData[TitleData] = value;
    public static string GetTitle<T>(this ViewDataDictionary<T> viewData) => (string)viewData[TitleData] ?? "";
}

Atur data di halaman

ViewData.SetTitle("abc");

Pilihan 2

Pilihan lain, membuat deklarasi lapangan lebih mudah.

public static class ViewDataExtensions
{
    public static ViewDataField<string, V> Title<V>(this ViewDataDictionary<V> viewData) => new ViewDataField<string, V>(viewData, "Title", "");
}

public class ViewDataField<T,V>
{
    private readonly ViewDataDictionary<V> _viewData;
    private readonly string _field;
    private readonly T _defaultValue;

    public ViewDataField(ViewDataDictionary<V> viewData, string field, T defaultValue)
    {
        _viewData = viewData;
        _field = field;
        _defaultValue = defaultValue;
    }

    public T Value {
        get => (T)(_viewData[_field] ?? _defaultValue);
        set => _viewData[_field] = value;
    }
}

Atur data di halaman. Deklarasi lebih mudah daripada opsi pertama, tetapi sintaks penggunaan sedikit lebih panjang.

ViewData.Title().Value = "abc";

Opsi # 3

Kemudian dapat menggabungkannya dengan mengembalikan satu objek yang berisi semua bidang terkait tata letak dengan nilai defaultnya.

public static class ViewDataExtensions
{
    private const string LayoutField = "Layout";
    public static LayoutData Layout<T>(this ViewDataDictionary<T> viewData) => 
        (LayoutData)(viewData[LayoutField] ?? (viewData[LayoutField] = new LayoutData()));
}

public class LayoutData
{
    public string Title { get; set; } = "";
}

Atur data di halaman

var layout = ViewData.Layout();
layout.Title = "abc";

Opsi ketiga ini memiliki beberapa manfaat dan menurut saya merupakan opsi terbaik dalam banyak kasus:

  • Deklarasi bidang dan nilai default paling sederhana.

  • Sintaks penggunaan paling sederhana saat mengatur beberapa bidang.

  • Memungkinkan pengaturan berbagai jenis data di ViewData (mis. Tata Letak, Header, Navigasi).

  • Mengizinkan kode dan logika tambahan dalam kelas LayoutData.

PS Jangan lupa untuk menambahkan namespace ViewDataExtensions di _ViewImports.cshtml

Etienne Charland
sumber
0

Anda dapat membuat file pisau cukur di folder App_Code dan kemudian mengaksesnya dari halaman tampilan Anda.

Proyek> Repositori / IdentityRepository.cs

namespace Infrastructure.Repository
{
    public class IdentityRepository : IIdentityRepository
    {
        private readonly ISystemSettings _systemSettings;
        private readonly ISessionDataManager _sessionDataManager;

        public IdentityRepository(
            ISystemSettings systemSettings
            )
        {
            _systemSettings = systemSettings;
        }

        public string GetCurrentUserName()
        {
            return HttpContext.Current.User.Identity.Name;
        }
    }
}

Project> App_Code / IdentityRepositoryViewFunctions.cshtml:

@using System.Web.Mvc
@using Infrastructure.Repository
@functions
{
    public static IIdentityRepository IdentityRepositoryInstance
    {
        get { return DependencyResolver.Current.GetService<IIdentityRepository>(); }
    }

    public static string GetCurrentUserName
    {
        get
        {
            var identityRepo = IdentityRepositoryInstance;
            if (identityRepo != null)
            {
                return identityRepo.GetCurrentUserName();
            }
            return null;
        }
    }
}

Project> Views / Shared / _Layout.cshtml (atau file .cshtml lainnya)

<div>
    @IdentityRepositoryViewFunctions.GetCurrentUserName
</div>
Joel Wiklund
sumber
-1

alih-alih melalui ini, Anda selalu dapat menggunakan pendekatan lain yang juga cepat

buat tampilan parsial baru di Direktori Bersama dan panggil tampilan parsial Anda di tata letak sebagai

@Html.Partial("MyPartialView")

dalam tampilan parsial Anda, Anda dapat memanggil db Anda dan melakukan apa pun yang ingin Anda lakukan

@{
    IEnumerable<HOXAT.Models.CourseCategory> categories = new HOXAT.Models.HOXATEntities().CourseCategories;
}

<div>
//do what ever here
</div>

dengan asumsi Anda telah menambahkan Database Kerangka Kerja Entitas Anda

Asad Ali
sumber
1
Downcasting karena seharusnya tidak menjadi tanggung jawab View untuk mendapatkan Modelnya sendiri.
Oxonhammer
-1

Sungguh luar biasa bahwa tidak ada yang mengatakan ini di sini. Meneruskan model tampilan melalui pengontrol dasar akan berantakan. Kami menggunakan klaim pengguna untuk meneruskan info ke halaman tata letak (untuk menampilkan data pengguna di bilah navigasi misalnya). Ada satu keuntungan lagi. Data disimpan melalui cookie, jadi tidak perlu mengambil data di setiap permintaan melalui parsial. Lakukan saja beberapa googling "klaim identitas bersih asp".

makore
sumber
@CodeS apa? Saya memberikan solusi.
makore
Saya buruk, mengira ini adalah pertanyaan tetapi lihat itu tanggapan sekarang, dihapus.
CodeSmith
Jika ini adalah upaya menjawab pertanyaan, maka harus diklarifikasi. Komentar ditoleransi tetapi tidak boleh mendominasi keseluruhan jawaban; juga, tips tentang apa yang ke google bukan merupakan jawaban yang valid.
tripleee
-6

Anda bisa menggunakan seperti ini:

 @{ 
    ApplicationDbContext db = new ApplicationDbContext();
    IEnumerable<YourModel> bd_recent = db.YourModel.Where(m => m.Pin == true).OrderByDescending(m=>m.ID).Select(m => m);
}
<div class="col-md-12">
    <div class="panel panel-default">
        <div class="panel-body">
            <div class="baner1">
                <h3 class="bb-hred">Recent Posts</h3>
                @foreach(var item in bd_recent)
                {
                    <a href="/BaiDangs/BaiDangChiTiet/@item.ID">@item.Name</a>
                }
            </div>
        </div>
    </div>
</div>
Ngô Đức Tuấn
sumber
7
Menghubungkan dengan database dalam tampilan adalah ide yang sangat buruk.
1_bug