मैं जो देखता हूं वह एक स्ट्रिंग लेआउट संपत्ति है। लेकिन मैं स्पष्ट रूप से लेआउट के लिए एक मॉडल कैसे पारित कर सकता हूं?
Model
में उपलब्ध है _Layout
। मैं MVC5 का उपयोग कर रहा हूं।
मैं जो देखता हूं वह एक स्ट्रिंग लेआउट संपत्ति है। लेकिन मैं स्पष्ट रूप से लेआउट के लिए एक मॉडल कैसे पारित कर सकता हूं?
Model
में उपलब्ध है _Layout
। मैं MVC5 का उपयोग कर रहा हूं।
जवाबों:
लगता है कि अगर आपने इस समस्या को देखा है तो आपने अपने व्यूअमॉडल को थोड़ा गलत बनाया है।
व्यक्तिगत रूप से मैं कभी भी लेआउट पृष्ठ नहीं लिखूंगा। लेकिन अगर आप ऐसा करना चाहते हैं, तो आपके पास एक बेस व्यूमॉडल होना चाहिए, जो आपके अन्य व्यूमॉडल से विरासत में मिले और अपने लेआउट को बेस व्यूमॉडल में टाइप करें और आप एक बार विशिष्ट पेजों को।
उदाहरण: नियंत्रक:
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;
}
}
उदाहरण पृष्ठ का शीर्ष पृष्ठ
@{
var viewModel = (MainLayoutViewModel)ViewBag.MainLayoutViewModel;
}
अब आप टाइप किए गए ऑब्जेक्ट पर पूर्ण पहुंच के साथ अपने लेआउट पेज में चर 'viewModel' का संदर्भ ले सकते हैं।
मुझे यह दृष्टिकोण पसंद है क्योंकि यह नियंत्रक है जो लेआउट को नियंत्रित करता है, जबकि व्यक्तिगत पेज व्यूमोडल लेआउट अज्ञेयवादी रहता है।
MVC कोर के लिए नोट्स
IActionFilter
कर रहा है और एक ही काम कर रहा है OnActionExecuting
। MyActionFilter
अपने पर रखो 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;
}
}
}
यह बहुत ही मूल सामग्री है, बस आपको एक बेस व्यू मॉडल बनाना और सभी को सुनिश्चित करना है! और मैं सभी का मतलब है! आपके विचारों का जो कभी उस लेआउट का उपयोग करेगा, उस आधार मॉडल का उपयोग करने वाले विचार प्राप्त करेगा!
public class SomeViewModel : ViewModelBase
{
public bool ImNotEmpty = true;
}
public class EmptyViewModel : ViewModelBase
{
}
public abstract class ViewModelBase
{
}
_Layout.cshtml में:
@model Models.ViewModelBase
<!DOCTYPE html>
<html>
and so on...
सूचकांक में (उदाहरण के लिए) होम कंट्रोलर में विधि:
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 में पास करना एक त्रुटि है, कुछ उपयोगकर्ता जानकारी पारित की जा सकती है और नियंत्रक नियंत्रकों श्रृंखला में डेटा को आबाद किया जा सकता है, इसलिए केवल एक कार्यान्वयन की आवश्यकता है।
स्पष्ट रूप से अधिक उन्नत उद्देश्य के लिए आपको इंजेक्शन का उपयोग करके कस्टम स्टैटिक कॉन्टैक्स बनाने पर विचार करना चाहिए और _Layout.chml में उस मॉडल नेमस्पेस को शामिल करना चाहिए।
लेकिन बुनियादी उपयोगकर्ताओं के लिए यह चाल चलेगा
एक सामान्य समाधान एक बेस व्यू मॉडल बनाना है जिसमें लेआउट फ़ाइल में उपयोग किए जाने वाले गुण शामिल हैं और फिर आधार मॉडल से संबंधित पृष्ठों पर उपयोग किए गए मॉडल में इनहेरिट करना है।
इस दृष्टिकोण के साथ समस्या यह है कि आपने अब अपने आप को एक मॉडल की समस्या में बंद कर दिया है, केवल एक दूसरे वर्ग से विरासत में मिल सकता है, और शायद आपका समाधान ऐसा है कि आप जिस मॉडल का उपयोग कर सकते हैं, उस पर विरासत का उपयोग नहीं कर सकते।
मेरा समाधान आधार दृश्य मॉडल के साथ भी शुरू होता है:
public class LayoutModel
{
public LayoutModel(string title)
{
Title = title;
}
public string Title { get;}
}
तब मैं जो उपयोग करता हूं वह लेआउटमॉडल का एक सामान्य संस्करण है जो इस तरह से लेआउटमॉडल से विरासत में मिला है:
public class LayoutModel<T> : LayoutModel
{
public LayoutModel(T pageModel, string title) : base(title)
{
PageModel = pageModel;
}
public T PageModel { get; }
}
इस समाधान के साथ मैंने लेआउट मॉडल और मॉडल के बीच विरासत की आवश्यकता को काट दिया है।
तो अब मैं आगे जा सकते हैं और इस तरह Layout.cshtml में LayoutModel का उपयोग कर सकते हैं:
@model LayoutModel
<!doctype html>
<html>
<head>
<title>@Model.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>
और एक पेज पर आप इस तरह जेनेरिक लेआउटमॉडल का उपयोग कर सकते हैं:
@model LayoutModel<Customer>
@{
var customer = Model.PageModel;
}
<p>Customer name: @customer.Name</p>
अपने नियंत्रक से आप केवल एक प्रकार का लेआउट लौटाते हैं:
public ActionResult Page()
{
return View(new LayoutModel<Customer>(new Customer() { Name = "Test" }, "Title");
}
आप न केवल आंशिक दृश्य के लिए आवश्यक मॉडल पास करने वाले i के अपने विशिष्ट नियंत्रक के साथ एक नया आंशिक दृश्य जोड़ते हैं और अंत में RenderPartial या RenderAction का उपयोग करके अपने Layout.cshtml पर उल्लिखित आंशिक दृश्य रेंडर करते हैं?
मैं इस विधि का उपयोग उपयोगकर्ता की जानकारी जैसे नाम, प्रोफ़ाइल चित्र और आदि में लॉग दिखाने के लिए करता हूँ।
पुराने प्रश्न लेकिन MVC5 डेवलपर्स के लिए समाधान का उल्लेख करने के लिए, आप Model
संपत्ति को देखने में उपयोग कर सकते हैं ।
Model
दोनों दृश्य और लेआउट में संपत्ति एक ही साथ assosiated है ViewDataDictionary
ताकि आप लेआउट पृष्ठ पर अपने मॉडल पारित करने के लिए किसी भी अतिरिक्त काम करने के लिए नहीं है, वस्तु, और आप की घोषणा करने की जरूरत नहीं है@model MyModelName
लेआउट में।
लेकिन ध्यान दें कि जब आप @Model.XXX
लेआउट में उपयोग करते हैं तो इंटेलीजेंस संदर्भ मेनू दिखाई नहीं देगा क्योंकि Model
यहां एक गतिशील वस्तु है जैसे कि ViewBag
।
हो सकता है कि यह तकनीकी रूप से इसे संभालने का उचित तरीका नहीं है, लेकिन मेरे लिए सबसे सरल और उचित समाधान सिर्फ एक वर्ग बनाना है और इसे लेआउट में त्वरित करना है। यह इसे करने के अन्यथा सही तरीके से एक बार अपवाद है। यदि यह लेआउट की तुलना में अधिक किया जाता है, तो आपको अपनी परियोजना में आगे बढ़ने से पहले अपने किए गए कार्यों के बारे में गंभीरता से पुनर्विचार करने की आवश्यकता है।
public class MyLayoutModel {
public User CurrentUser {
get {
.. get the current user ..
}
}
}
फिर दृश्य में
@{
// Or get if from your DI container
var myLayoutModel = new MyLayoutModel();
}
, .net कोर में आप इसे छोड़ सकते हैं और निर्भरता इंजेक्शन का उपयोग कर सकते हैं।
@inject My.Namespace.IMyLayoutModel myLayoutModel
यह उन क्षेत्रों में से एक है जो छायादार है। लेकिन मैं यहाँ जो जटिल विकल्प देख रहा हूँ, उसे देखते हुए, मुझे लगता है कि यह व्यावहारिकता के नाम पर बनाने के लिए एक बढ़िया अपवाद से अधिक है। खासकर यदि आप इसे सरल रखना सुनिश्चित करते हैं और यह सुनिश्चित करते हैं कि कोई भी भारी तर्क है (मैं तर्क दूंगा कि वास्तव में कोई भी नहीं होना चाहिए, लेकिन आवश्यकताएं अलग हैं) एक अन्य वर्ग / परत में है जहां यह है। यह मूल रूप से सिर्फ एक दृश्य के लिए अपने सभी नियंत्रकों या मॉडलों को प्रदूषित करने से बेहतर है।
इसे संग्रहीत करने का एक और तरीका है।
में BaseController
वर्ग एक विधि है कि उदाहरण के लिए की तरह एक मॉडल वर्ग रिटर्न पैदा करते हैं।
public MenuPageModel GetTopMenu() { var m = new MenuPageModel(); // populate your model here return m; }
Layout
पेज में आप उस तरीके को कॉल कर सकते हैंGetTopMenu()
@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>
मान लें कि आपका मॉडल वस्तुओं का संग्रह है (या शायद एक ही वस्तु)। मॉडल में प्रत्येक वस्तु के लिए निम्न कार्य करें।
1) ViewBag में वह ऑब्जेक्ट डालें जिसे आप दिखाना चाहते हैं। उदाहरण के लिए:
ViewBag.YourObject = yourObject;
2) _Layout.cshtml के शीर्ष पर एक उपयोग कथन जोड़ें जिसमें आपकी वस्तुओं के लिए वर्ग परिभाषा है। उदाहरण के लिए:
@use YourApplication.YourClasses;
3) जब आप अपने ऑबजेक्ट को संदर्भित करते हैं तो _Layout में इसे डालें। आपने जो (2) में किया उसके कारण आप कास्ट को लागू कर सकते हैं।
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; }
}
अपने लेआउट में IContainsMyModel का उपयोग करें।
हल किया। इंटरफेस नियम।
उदाहरण के लिए
@model IList<Model.User>
@{
Layout="~/Views/Shared/SiteLayout.cshtml";
}
नए @model निर्देश के बारे में अधिक पढ़ें