Gördüğüm şey bir string Layout özelliği. Ancak bir modeli düzene nasıl aktarabilirim?
Yanıtlar:
Bu problemi yaşıyorsanız, görünüm modellerinizi biraz yanlış modellediniz gibi görünüyor.
Şahsen ben asla bir düzen sayfası yazmam. Ancak bunu yapmak istiyorsanız, diğer görünüm modellerinin miras aldığı bir temel görünüm modeline sahip olmanız ve mizanpajınızı temel görünüm modeline yazmanız ve belirli bir kez sayfalamanız gerekir.
Örnek: Denetleyici:
public class MyController : Controller
{
public MainLayoutViewModel MainLayoutViewModel { get; set; }
public MyController()
{
this.MainLayoutViewModel = new MainLayoutViewModel();//has property PageTitle
this.MainLayoutViewModel.PageTitle = "my title";
this.ViewData["MainLayoutViewModel"] = this.MainLayoutViewModel;
}
}
Düzen Sayfasının Başına Örnek
@{
var viewModel = (MainLayoutViewModel)ViewBag.MainLayoutViewModel;
}
Artık, yazılan nesneye tam erişimle düzen sayfanızdaki 'viewModel' değişkenine başvurabilirsiniz.
Bu yaklaşımı seviyorum çünkü mizanpajı kontrol eden kontrolcüdür, oysa münferit sayfa görünüm modelleri mizanpajdan bağımsız kalır.
MVC Core için notlar
IActionFilter
ve aynı işi yapmaktır OnActionExecuting
. Put MyActionFilter
Aşağıdaki yerlerde de MyController
.
public class MyActionFilter: Attribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
var myController= context.Controller as MyController;
if (myController!= null)
{
myController.Layout = new MainLayoutViewModel
{
};
myController.ViewBag.MainLayoutViewModel= myController.Layout;
}
}
}
bu oldukça basit şeyler, tek yapmanız gereken bir temel görünüm modeli oluşturmak ve TÜMÜNÜ sağlamaktır! ve TÜM demek istedim! Bu düzeni kullanacak olan görünümlerinizden tanesi o temel modeli kullanan görünümler alacak!
public class SomeViewModel : ViewModelBase
{
public bool ImNotEmpty = true;
}
public class EmptyViewModel : ViewModelBase
{
}
public abstract class ViewModelBase
{
}
_Layout.cshtml’de:
@model Models.ViewModelBase
<!DOCTYPE html>
<html>
and so on...
ev denetleyicisindeki Dizin (örneğin) yönteminde:
public ActionResult Index()
{
var model = new SomeViewModel()
{
};
return View(model);
}
Index.cshtml:
@model Models.SomeViewModel
@{
ViewBag.Title = "Title";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
_layout'a bir model iletmenin bir hata olduğuna katılmıyorum, bazı kullanıcı bilgileri aktarılabilir ve veriler denetleyicilerin devralma zincirinde doldurulabilir, bu nedenle yalnızca bir uygulamaya ihtiyaç vardır.
Açıkçası daha gelişmiş amaçlar için, enjeksiyon kullanarak özel statik içerik oluşturmayı düşünmeli ve bu model ad alanını _Layout.cshtml'ye dahil etmelisiniz.
ancak temel kullanıcılar için bu hile yapacak
Yaygın bir çözüm, yerleşim dosyasında kullanılan özellikleri içeren bir temel görünüm modeli yapmak ve ardından temel modelden ilgili sayfalarda kullanılan modellere devralmaktır.
Bu yaklaşımla ilgili sorun, artık kendinizi bir model problemine kilitlemiş olmanızdır, ancak başka bir sınıftan miras alabilir ve belki de çözümünüz, amaçladığınız model üzerinde kalıtımı kullanamayacağınız şekildedir.
Çözümüm ayrıca bir temel görünüm modeliyle başlıyor:
public class LayoutModel
{
public LayoutModel(string title)
{
Title = title;
}
public string Title { get;}
}
Daha sonra kullandığım şey, LayoutModel'den miras alan LayoutModel'in genel bir sürümüdür, örneğin:
public class LayoutModel<T> : LayoutModel
{
public LayoutModel(T pageModel, string title) : base(title)
{
PageModel = pageModel;
}
public T PageModel { get; }
}
Bu çözümle, yerleşim modeli ile model arasında miras alma ihtiyacını ortadan kaldırdım.
Şimdi devam edip Layout.cshtml'deki LayoutModel'i şu şekilde kullanabilirim:
@model LayoutModel
<!doctype html>
<html>
<head>
<title>@Model.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>
Ve bir sayfada genel LayoutModel'i şu şekilde kullanabilirsiniz:
@model LayoutModel<Customer>
@{
var customer = Model.PageModel;
}
<p>Customer name: @customer.Name</p>
Denetleyicinizden LayoutModel türünde bir model döndürmeniz yeterlidir:
public ActionResult Page()
{
return View(new LayoutModel<Customer>(new Customer() { Name = "Test" }, "Title");
}
Neden gerekli modeli kısmi görünüme geçiren kendi özel denetleyicisine sahip yeni bir Kısmi Görünüm eklemiyorsunuz ve son olarak, söz konusu kısmi görünümü RenderPartial veya RenderAction kullanarak Layout.cshtml'nizde Render yapmıyorsunuz?
Bu yöntemi oturum açmış kullanıcının ad, profil resmi vb. Bilgilerini göstermek için kullanıyorum.
Eski bir soru, ancak MVC5 geliştiricileri için çözümden bahsetmek gerekirse, Model
özelliği görünümdeki ile aynı şekilde kullanabilirsiniz .
Model
Görünümü ve düzeni hem de özellik aynı sahip prosedürlerdir edilir ViewDataDictionary
Eğer düzeni sayfasına modelinizi geçmesine herhangi bir ekstra çalışma yapmak zorunda kalmamak, nesne ve bir açıklamadan gerekmez@model MyModelName
düzeninde.
Ancak @Model.XXX
, mizanpajda kullandığınızda, intelliSense bağlam menüsünün görünmeyeceğine dikkat edin, çünkü Model
burası aynı dinamik bir nesne ViewBag
.
Belki teknik olarak bunun üstesinden gelmenin doğru yolu değil, ama benim için en basit ve en makul çözüm, bir sınıf oluşturmak ve onu düzende somutlaştırmaktır. Aksi takdirde doğru şekilde yapmanın bir defalık istisnasıdır. Bu, düzende olduğundan daha fazla yapılırsa, ne yaptığınızı ciddi bir şekilde yeniden düşünmeniz ve projenizde ilerlemeden önce belki birkaç öğretici daha okumalısınız.
public class MyLayoutModel {
public User CurrentUser {
get {
.. get the current user ..
}
}
}
sonra görünümde
@{
// Or get if from your DI container
var myLayoutModel = new MyLayoutModel();
}
.net çekirdeğinde bunu atlayabilir ve bağımlılık enjeksiyonunu kullanabilirsiniz.
@inject My.Namespace.IMyLayoutModel myLayoutModel
Bu biraz gölgeli alanlardan biri. Ancak burada gördüğüm aşırı karmaşık alternatifler göz önüne alındığında, pratiklik adına yapmanın bir istisnadan daha fazlası olduğunu düşünüyorum. Özellikle basit tuttuğunuzdan ve herhangi bir ağır mantığın (gerçekten hiç olmaması gerektiğini, ancak gereksinimlerin farklı olduğunu) ait olduğu başka bir sınıfta / katmanda olduğundan emin olduğunuzdan emin olursanız. Temelde tek bir görünüm uğruna TÜM kontrol cihazlarınızı veya modellerinizi kirletmekten kesinlikle daha iyidir.
Arşivlemenin başka bir yolu var.
Sadece tüm denetleyiciler için BaseController sınıfını uygulayın .
Gelen BaseController
sınıfı, örneğin böyle bir model sınıf döndüren bir yöntem oluşturur.
public MenuPageModel GetTopMenu() { var m = new MenuPageModel(); // populate your model here return m; }
Layout
sayfada bu yöntemi çağırabilirsinizGetTopMenu()
@using GJob.Controllers <header class="header-wrapper border-bottom border-secondary"> <div class="sticky-header" id="appTopMenu"> @{ var menuPageModel = ((BaseController)this.ViewContext.Controller).GetTopMenu(); } @Html.Partial("_TopMainMenu", menuPageModel) </div> </header>
Modelinizin bir nesneler koleksiyonu (veya belki tek bir nesne) olduğunu varsayalım. Modeldeki her nesne için aşağıdakileri yapın.
1) Görüntülemek istediğiniz nesneyi ViewBag'e koyun. Örneğin:
ViewBag.YourObject = yourObject;
2) _Layout.cshtml'nin üstüne nesnelerinizin sınıf tanımını içeren bir using ifadesi ekleyin. Örneğin:
@ YourApplication.YourClasses kullanarak;
3) _Layout'ta Nesnenize başvurduğunuzda onu yayınlayın. (2) 'de yaptığınız şeyden dolayı alçı uygulayabilirsiniz.
public interface IContainsMyModel
{
ViewModel Model { get; }
}
public class ViewModel : IContainsMyModel
{
public string MyProperty { set; get; }
public ViewModel Model { get { return this; } }
}
public class Composition : IContainsMyModel
{
public ViewModel ViewModel { get; set; }
}
Düzeninizde IContainsMyModel kullanın.
Çözüldü. Arayüzler kuralı.
Örneğin
@model IList<Model.User>
@{
Layout="~/Views/Shared/SiteLayout.cshtml";
}
Yeni @model yönergesi hakkında daha fazlasını okuyun