Tüm sayfalarda ortak olan düzene veri aktarın


125

Düzen sayfası olan bir web sitem var. Bununla birlikte, bu düzen sayfası, tüm sayfa modelinin bu tür sayfa başlığını, sayfa adını ve aslında bulunduğumuz yeri, bazı eylemleri gerçekleştiren bir HTML yardımcısı için sağlaması gereken verilere sahiptir. Ayrıca her sayfanın kendi görünüm modelleri özellikleri vardır.

Bunu nasıl yapabilirim? Bir düzen yazmak kötü bir fikir gibi görünüyor, ancak bu bilgileri nasıl geçirebilirim?


10
Buradaki yanıtları okuyan herkes için, burada yayınlananlardan çok daha basit ve daha temiz bir çözüm göreceğiniz stackoverflow.com/a/21130867/706346 adresini ziyaret edin .
Avrohom Yisroel

5
@AvrohomYisroel iyi öneri. Ancak @ Colin Bacon'un yaklaşımını tercih ediyorum çünkü güçlü yazılmış ve ViewBag. Belki bir tercih meselesi. Yine de yorumunuza olumlu oy verdi
JP Hellemons

mvc 5 için bu yanıta bakın: stackoverflow.com/a/46783375/5519026
Laz Ziya

Yanıtlar:


143

Her sayfaya aynı özellikleri aktarmanız gerekiyorsa, tüm görünüm modelleriniz tarafından kullanılan bir temel görünüm modeli oluşturmak akıllıca olacaktır. Düzen sayfanız daha sonra bu temel modeli alabilir.

Bu verilerin arkasında gerekli mantık varsa, bu, tüm denetleyicileriniz tarafından kullanılan bir temel denetleyiciye konulmalıdır.

Yapabileceğiniz çok şey var, önemli yaklaşım aynı kodu birden çok yerde tekrarlamamaktır.

Düzenleme: Aşağıdaki yorumlardan güncelleyin

İşte kavramı göstermek için basit bir örnek.

Tüm görünüm modellerinin miras alacağı bir temel görünüm modeli oluşturun.

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

public class HomeViewModel : ViewModelBase
{
}

Düzen sayfanız bunu model olarak alabilir.

@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>

Son olarak verileri eylem yönteminde ayarlayın.

public class HomeController
{
    public ActionResult Index()
    {
        return this.View(new HomeViewModel { Name = "Bacon" });
    }
}

12
Ancak veriler düzende kullanılır. Verileri düzene nasıl aktarabilirim?
Rushino

2
Mükemmel! Hatamı gördüm. Modeli görünüme geçirmeyi unuttum .. Ne kötü bir hata. Teşekkürler!
Rushino

7
bu yaklaşımla ilgili sorun, bazen her görünümde bir ViewModel olmamasıdır, bu nedenle bu durumda bu işe yaramaz: O /
Cacho Santa

17
Ancak bu, her denetleyicinin ve her eylemin {Name = "Bacon"} kodunu içermesini gerektirmez mi? Ve ViewModelBase'e başka bir özellik eklemek istersem, her denetleyiciye ve her eyleme gidip bu özelliği doldurmak için kodu eklemem gerekir mi? "Mantık gerekiyorsa [...] bu bir temel denetleyiciye [...] konulmalı" dediniz. Bu, her denetleyicide ve her eylemde tekrarlanan bu kodu ortadan kaldırmak için nasıl çalışır?
Lee

5
@Lee Tüm sayfalarda ortak verilerse, bunu koyacağınız yer bir temel denetleyicidir. Denetleyicileriniz daha sonra bu temel denetleyiciden miras alır. ör public class HomeController : BaseController. Bu şekilde ortak kodun yalnızca bir kez yazılması gerekir ve tüm kontrolörlere uygulanabilir.
Colin Bacon

73

Düzende ustura için RenderAction html yardımcısını kullandım.

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

Basit bir ip için ihtiyacım vardı. Bu yüzden eylemim dizeyi döndürür ve kolayca görünürde yazar. Ancak karmaşık verilere ihtiyacınız varsa, PartialViewResult ve modelini döndürebilirsiniz.

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

Modelinizi oluşturduğunuz '_maPartialView.cshtml' kısmi görünümünün başlangıcına koymanız yeterlidir.

@model List<WhatEverYourObjeIs>

Daha sonra modeldeki verileri bu kısmi görünümde html ile kullanabilirsiniz.


18
Bu açık ara en iyi cevaptır!
zencefilli çocuk

@gingerbreadboy, bunun iyi bir kapsüllemeyi ve endişelerin ayrılmasını teşvik ettiğini kabul etti.
A-Dubb

35

Diğer bir seçenek, mizanpajda ihtiyaç duyacağınız tüm özelliklere sahip ayrı bir LayoutModel sınıfı oluşturmak ve ardından bu sınıfın bir örneğini ViewBag'e doldurmaktır. Doldurmak için Controller.OnActionExecuting yöntemini kullanıyorum. Ardından, düzen başlangıcında bu nesneyi ViewBag'den geri çekebilir ve bu güçlü yazılmış nesneye erişmeye devam edebilirsiniz.


1
Bu aslında en az acı veren çözüm gibi geliyor, herhangi bir dezavantajı var mı? +1
formatc

2
Kesinlikle en iyi çözüm ve herhangi bir dezavantaj görmüyorum.
Wiktor Zychla

7
Bunun sana ne verdiğini anlamıyorum. Düzen için ihtiyaç duyduğunuz tüm özelliklere sahip bir sınıfınız varsa, neden onu ViewBag'e eklemeye zahmet edesiniz ki, sadece tekrar geri çevirmek zorunda kalasınız? Modeli yerleşim görünümünde kullanın, modeli içine yine de doldurabilirsiniz OnActionExecuting. ViewBag'i kullanmak, kontrol cihazınızda tip güvenliğini kaybettiğiniz anlamına gelir, asla iyi bir şey değildir.
Colin Bacon

3
Bunun bana verdiği şey, halihazırda var olan bir projede tüm kontrolörlerin tüm yöntemlerinde tek "süper" modelden miras almak için tüm modelleri yeniden yapılandırmak zorunda kalmadan yerleşim için bir model ekleme yeteneği. Sıfırdan başlıyorsanız, tüm modellerinizi bunun yerine ortak kökten türetmeyi seçebilirsiniz.
DenNukem

5
@ColinBacon bu seçeneğin bir başka avantajı da Eylemlerinizin her zaman görünüm modellerine sahip olmasına gerek olmamasıdır. Ayrıca, geliştiricilerin görüş modellerini her zaman bir tabandan miras almaları gerektiğini bilmelerinin bir dezavantaj olduğunu iddia ediyorum.
Josh Noe

28

Muhtemelen, bunun birincil kullanım durumu, tüm (veya çoğunluğu) denetleyici eylemleri için görünüme bir temel model almaktır.

Bunu göz önünde bulundurarak, Colin Bacon'un cevabını destekleyen bu cevapların birkaçının bir kombinasyonunu kullandım.

Bir görünüme dönmek için bir görünüm modelini doldurduğumuzdan, bunun hala denetleyici mantığı olduğu doğrudur. Dolayısıyla, bunu yerleştirmek için doğru yer kontrolördedir.

Bunun tüm kontrolörlerde olmasını istiyoruz çünkü bunu düzen sayfası için kullanıyoruz. Düzen sayfasında işlenen kısmi görünümler için kullanıyorum.

Ayrıca, güçlü bir şekilde yazılmış bir ViewModel'in ek avantajını da istiyoruz

Böylece BaseViewModel ve BaseController oluşturdum. Tüm ViewModels Denetleyicileri, sırasıyla BaseViewModel ve BaseController'dan miras alır.

Kod:

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!";
    }
}

Bu SO gönderisinden alınan OnActionExecuted kullanımına dikkat edin

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>

Umarım bu yardımcı olur.


2
Bu yaklaşımı kullandım, ancak temel sınıftan ziyade bir arayüzden miras almayı tercih ediyorum. Ben de yaptım: var model = filterContext.Controller.ViewData.Model as IBaseViewModel if (model! = Null) {model.AwesomeModelProperty = "Awesome Property Value"; }
Tom Gerken

2
harika cevap, bunu diğerlerine tercih ettim.
Jynn

1
Harika cevap, ama bir sorum var. "Ya ViewModels içermeyen bazı görünümlerim varsa ...?"
Isma Haro

Bunu denedim, ancak Dizin Eyleminde, OnActionExecuted, FooterModel'i doldurur ve ardından boş bir FooterModel ile yeni bir HomeIndexModel oluşturulur :(
SteveCav

1
@drizzie: temel denetleyicinizde model, Filter yöntemindeki yerel bir değişkendir: var model = filterContext.Controller.ViewData.Model, BaseViewModel olarak. MVC'nin bu yerel değişkenin HomeController'ın görüntülemek için gönderdiği modelle aynı olduğunu nasıl anladığını anlamıyorum.
Hooman Bahreini

9

Eylemlerle uğraşmak veya modeli değiştirmek zorunda değilsiniz, sadece bir temel kontrolör kullanın ve mevcut kontrolcüyü düzen görünümü bağlamından yayınlayın.

İstenen ortak verilerle (başlık / sayfa / konum vb.) Ve eylem başlatma ile bir temel kontrolör oluşturun ...

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

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {

        MyCommonValue = 12345;

        base.OnActionExecuting(filterContext);
    }
}

Her denetleyicinin temel denetleyiciyi kullandığından emin olun ...

public class UserController:_BaseController {...

Mevcut temel denetleyiciyi _Layout.cshmlsayfanızdaki görünüm bağlamından yayınlayın ...

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

Artık düzen sayfanızdan temel denetleyicinizdeki değerlere başvurabilirsiniz.

@myController.MyCommonValue

GÜNCELLEME

Ayrıca kullanmanıza izin verecek bir sayfa uzantısı da oluşturabilirsiniz 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;
}

O zaman sadece this.Controller()kontrolörü istediğinizde kullanmayı hatırlamanız gerekir .

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

veya devralan belirli bir denetleyici _BaseController...

@{
    var myController = this.Controller<MyControllerType>();
}

Bunun .net çekirdeğindeki karşılığı nedir? ViewContext.Controller olmadığı ve kalıtım zincirinde bazı değişiklikler olduğu için
Jayanth Thyagarajan

4

Tüm bir modeli geçmek istiyorsanız, düzende böyle gidin:

@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>

ve bunu denetleyiciye ekleyin:

public ActionResult _Header(ViewAsModelBase model)

4

Bu yanıtların hiçbirinin büyük bir kurumsal uygulama için yeterince esnek olduğunu düşünmüyorum. ViewBag'i aşırı kullanmanın hayranı değilim, ancak bu durumda, esneklik için bir istisna yaparım. İşte yapacağım şey ...

Tüm denetleyicilerinizde bir temel denetleyiciniz olmalıdır. Yerleşim verilerinizi OnActionExecuting'e (veya bunu ertelemek istiyorsanız OnActionExecuted) ekleyin ...

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

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

Ardından _Layout.cshtml dosyanızda ViewModel'inizi ViewBag'den çekin ...

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

<h1>@model.Title</h1>

Veya...

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

Bunu yapmak, sayfanızın denetleyicilerinin kodlamasına veya modelleri görüntülemeye müdahale etmez.


Fikrinizi beğendim ama ya MyLayoutViewModeldinamik olarak oluşturduysanız, bazı parametreleri OnActionExecutingmetoda nasıl aktarabilirim ?
Rajmond Burgaj

1
Ah, hala ihtiyaç base.OnActionExecuting(filterContext)senin içinde OnActionExecutingyöntemle !!!
ErikE

4

Düzen görünüm modelini temsil eden bir temel görünüm oluşturmak korkunç bir yaklaşımdır. Düzende tanımlanan navigasyonu temsil eden bir modele sahip olmak istediğinizi düşünün. Yapmanız misiniz CustomersViewModel : LayoutNavigationViewModel? Neden? Neden navigasyon modeli verilerini çözümde sahip olduğunuz her bir görünüm modelinden geçirmelisiniz?

Düzen görünümü modeli kendi başına tahsis edilmeli ve geri kalan görünüm modellerini buna bağlı olmaya zorlamamalıdır.

Bunun yerine, bunu _Layout.cshtmldosyanızda yapabilirsiniz:

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

En önemlisi, ihtiyacımız yok new LayoutViewModel()ve bizim LayoutViewModeliçin çözülen tüm bağımlılıkları alacağız .

Örneğin

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

    public LayoutViewModel(DataContext dataContext, ApplicationUserManager userManager)
    {
    }
}

Bu modeli nerede dolduruyorsunuz? BaseController'da da mı?
ndberg

Bunun ScopedASP..Net Core'daki bir düzen modeli nesnesi için de iyi bir fikir olacağını düşünüyorum .
James Wilkins

Görünümün bir bağımlılık getirmesine izin vermezdim. Bu kesinlikle "MVC" değil. Servis Bulucu bir anti-modeldir .
Jiveman

Yaygın inancın aksine, Servis Bulucu bir anti-model değildir ve aslında bunun MVC ile hiçbir ilgisi yoktur, sadece @ Jiveman'da vızıltı mı atıyorsunuz? blog.gauffin.org/2012/09/service-locator-is-not-an-anti-pattern
hyankov

Jgauffin'in bu makaledeki ana noktası, SL'nin en azından bazı geçerli kullanımları olabileceğinden, "anti-pattern" teriminin Service Locator'a uygulanmaması gerektiği gibi görünüyor. Adil bir nokta. Bununla birlikte, kendi tartışma yorumlarının bazılarında açıkça görüldüğü gibi, SL'nin kütüphaneler ve çerçeveler oluştururken geçerli bir yaklaşım olabileceğini, ancak uygulamaları oluştururken bunun mutlaka tavsiye edilmediğini öne sürüyor (OP'nin sorusunu ve buradaki tartışmayı Etrafında dönen).
Jiveman

3

Diğer yanıtlar, modeli yerleşim sayfamıza nasıl geçirebileceğimizle ilgili hemen hemen her şeyi kapsıyor. Ancak, mizanpajınızda herhangi bir model veya kısmi görünüm kullanmadan değişkenleri mizanpaj sayfanıza dinamik olarak aktarabileceğiniz bir yol buldum. Bu modele sahip olduğunuzu varsayalım -

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

Ve dinamik olarak şehir ve eyalete sahip olmak istiyorsunuz. Örneğin

index.cshtml dosyanızda bu iki değişkeni ViewBag'e koyabilirsiniz

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

Daha sonra layout.cshtml dosyanızda bu viewbag değişkenlerine erişebilirsiniz.

<div class="text-wrap">
    <div class="heading">@ViewBag.City @ViewBag.State</div>
</div>

bu harika çalışıyor, @stun_Gravy rol veya kullanıcı erişim seviyesi gibi verileri aktarmak için ViewBag kullanıldığında bir düşüş var mı?
3not3

3

Bunu halletmenin başka bir yolu var. Mimari açıdan bakıldığında belki de en temiz yol değil, ama diğer cevaplarla ilgili çok fazla acıdan kaçınıyor. Basitçe Razor düzeninde bir hizmet enjekte edin ve ardından gerekli verileri alan bir yöntemi çağırın:

@inject IService myService

Daha sonra, düzen görünümünde:

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

Yine mimari açıdan temiz değil (tabii ki hizmet doğrudan görünümde enjekte edilmemelidir), ancak işi bitirir.


En temiz yol değil mi? Katılmıyorum. Bunun olabildiğince temiz olduğunu düşünüyorum: nesne, diğer denetleyicileri görmeleri gerekmeyen öğelerle "kirletmeden", oluşturulduğu yerden doğrudan olmasını istediğiniz yere aktarılır. @injectBence kullanmak en iyi çözüm.
dasblinkenlight

1
Bunu daha çok düşünmek belki haklısın. Bu yöntemin bu kadar acıdan kaçınması, belki de en temiz yol olduğunun bir işaretidir. Çok büyük bir ASP.NET Core uygulaması üzerinde çalışıyorum ve bu kalıbı gezinti kırıntı mantığı, çoğu sayfadaki başlık verileri, bunun gibi şeyler için kullanıyorum. Bunun yerine bu şekilde yaparak çok fazla acıdan kaçındım.
Andrew

2

Ayrıca, RenderSection'dan da yararlanabilirsiniz , Modelverilerinizi _Layoutgörünüme enjekte etmenize yardımcı olur .

Sen enjekte edebilir View ModelVeriler Json, Script, CSS, HTMLvb

Bu örnekte ben enjekte ediyorum Jsonbenim dan IndexView to LayoutGörünümü.

Index.chtml

@section commonLayoutData{

    <script>

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

    </script>

    }

_Layout.cshtml

@RenderSection("commonLayoutData", false)

Bu, ayrı bir Üs oluşturma ihtiyacını ortadan kaldırır View Model.

Umut birine yardım eder.


1
Yalnızca birkaç görünüm için belirli bir şey oluşturmanız gerektiğinde mükemmel çözüm .
Kunal

1

yaptığım çok basit ve işe yarıyor

Herhangi bir denetleyicide Statik özelliği bildirin veya şöyle isterseniz statik değerlerle bir veri sınıfı oluşturabilirsiniz:

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

Bu değerler, işlemlere göre kontrolörler tarafından güncellenebilir. bunları daha sonra _Layout'unuzda kullanabilirsiniz

_Layout.cshtml'de

@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType

1
Daha açık ve anlaşılır hale getirmek için cevabınıza bir açıklama eklemek her zaman faydalıdır. Lütfen stackoverflow.com/help/how-to-answer adresini okuyun .
32cupo

0

ViewData'da neden kimse uzatma yöntemleri önermedi?

Seçenek 1

Bana, sorunun en az müdahaleci ve en basit çözümü gibi görünüyor. Sabit kodlanmış dizeler yok. Hiçbir kısıtlama yoktur. Sihirli kodlama yok. Karmaşık kod yok.

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] ?? "";
}

Sayfadaki verileri ayarlayın

ViewData.SetTitle("abc");

Seçenek 2

Alan bildirimini kolaylaştıran başka bir seçenek.

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;
    }
}

Sayfadaki verileri ayarlayın. Bildirim ilk seçenekten daha kolaydır, ancak kullanım sözdizimi biraz daha uzundur.

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

3. Seçenek

Ardından, bunu, tüm düzen ile ilgili alanları içeren tek bir nesneyi varsayılan değerleriyle birleştirerek birleştirebilir.

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; } = "";
}

Sayfadaki verileri ayarlayın

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

Bu üçüncü seçeneğin birçok faydası vardır ve çoğu durumda en iyi seçenek olduğunu düşünüyorum:

  • Alanların ve varsayılan değerlerin en basit beyanı.

  • Birden fazla alan ayarlarken en basit kullanım sözdizimi.

  • ViewData'da çeşitli veri türlerinin ayarlanmasına izin verir (örn. Düzen, Başlık, Gezinme).

  • LayoutData sınıfı içinde ek kod ve mantığa izin verir.

PS ViewDataExtensions ad alanını _ViewImports.cshtml içine eklemeyi unutmayın


0

App_Code klasöründe bir ustura dosyası oluşturabilir ve ardından bu dosyaya görünüm sayfalarınızdan erişebilirsiniz.

Proje> Depo / 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;
        }
    }
}

Proje> 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;
        }
    }
}

Proje> Görünümler / Paylaşılan / _Layout.cshtml (veya başka herhangi bir .cshtml dosyası)

<div>
    @IdentityRepositoryViewFunctions.GetCurrentUserName
</div>

-1

bunu geçmek yerine her zaman hızlı olan başka bir yaklaşımı kullanabilirsiniz.

Paylaşılan Dizinde yeni bir kısmi görünüm oluşturun ve düzeninizde kısmi görünümünüzü

@Html.Partial("MyPartialView")

kısmi görünümünüzde db'nizi arayabilir ve yapmak istediğiniz şeyi gerçekleştirebilirsiniz

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

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

Entity Framework Veritabanınızı eklediğinizi varsayarsak


1
Kendi Modelini elde etme sorumluluğu asla Görüşün sorumluluğu olmamalıdır.
Oxonhammer

-1

Burada kimsenin bunu söylememesi inanılmaz. Bir görünüm modelini bir temel denetleyiciden geçirmek tam bir karmaşa. Yerleşim sayfasına bilgi iletmek için kullanıcı iddialarını kullanıyoruz (örneğin, gezinme çubuğunda kullanıcı verilerini göstermek için). Bir avantaj daha var. Veriler çerezler aracılığıyla saklanır, bu nedenle her istekte verilerin kısmi olarak geri alınmasına gerek yoktur. Sadece googling "asp net kimlik iddiaları" yapın.


@CodeSmith ne? Bir çözüm sunuyorum.
Makore

Benim hatam, bunun bir soru olduğunu düşündüm ama şimdi bir cevap olduğunu görün, silindi.
CodeSmith

Bu, soruyu cevaplama girişimiyse, açıklığa kavuşturulmalıdır. Yorum tolere edilir, ancak tüm cevaba hakim olmamalıdır; ayrıca, google'ın ne yapacağına dair ipuçları geçerli bir cevap oluşturmaz.
üçlü

-6

Bunun gibi kullanabilirsiniz:

 @{ 
    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>

7
Görünümde veritabanına bağlanmak gerçekten kötü bir fikir.
1_bug
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.