สิ่งที่ฉันเห็นคือคุณสมบัติเค้าโครงสตริง แต่ฉันจะส่งแบบจำลองไปจัดวางอย่างชัดเจนได้อย่างไร
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 Core
IActionFilterและทำงานแบบเดียวกันในOnActionExecuting. ใส่บนMyActionFilterMyController
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...
ในวิธี Index (ตัวอย่าง) ในตัวควบคุมที่บ้าน:
    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.cshtml
แต่สำหรับผู้ใช้ขั้นพื้นฐานสิ่งนี้จะทำตามเคล็ดลับ
วิธีแก้ปัญหาทั่วไปคือการสร้างโมเดลมุมมองฐานซึ่งมีคุณสมบัติที่ใช้ในไฟล์โครงร่างแล้วสืบทอดจากโมเดลพื้นฐานไปยังโมเดลที่ใช้บนเพจตามลำดับ
ปัญหาของแนวทางนี้คือตอนนี้คุณได้ขังตัวเองไว้ในปัญหาของโมเดลที่สามารถสืบทอดจากคลาสอื่นได้เท่านั้นและบางทีวิธีแก้ปัญหาของคุณอาจทำให้คุณไม่สามารถใช้การสืบทอดกับโมเดลที่คุณตั้งใจไว้ได้
โซลูชันของฉันเริ่มต้นด้วยโมเดลมุมมองฐาน:
public class LayoutModel
{
    public LayoutModel(string title)
    {
        Title = title;
    }
    public string Title { get;}
}
สิ่งที่ฉันใช้คือ LayoutModel เวอร์ชันทั่วไปซึ่งสืบทอดมาจาก LayoutModel ดังนี้:
public class LayoutModel<T> : LayoutModel
{
    public LayoutModel(T pageModel, string title) : base(title)
    {
        PageModel = pageModel;
    }
    public T PageModel { get; }
}
ด้วยโซลูชันนี้ฉันได้ยกเลิกความจำเป็นในการสืบทอดระหว่างโมเดลโครงร่างและโมเดล
ตอนนี้ฉันสามารถใช้ LayoutModel ใน Layout.cshtml ได้ดังนี้:
@model LayoutModel
<!doctype html>
<html>
<head>
<title>@Model.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>
และในหน้าคุณสามารถใช้ LayoutModel ทั่วไปได้ดังนี้:
@model LayoutModel<Customer>
@{
    var customer = Model.PageModel;
}
<p>Customer name: @customer.Name</p>
จากคอนโทรลเลอร์ของคุณคุณเพียงแค่ส่งคืนโมเดลประเภท LayoutModel:
public ActionResult Page()
{
    return View(new LayoutModel<Customer>(new Customer() { Name = "Test" }, "Title");
}
ทำไมคุณไม่เพิ่มมุมมองบางส่วนใหม่ด้วยคอนโทรลเลอร์เฉพาะของฉันเองโดยส่งโมเดลที่ต้องการไปยังมุมมองบางส่วนและในที่สุดก็แสดงมุมมองบางส่วนที่กล่าวถึงบน Layout.cshtml ของคุณโดยใช้ RenderPartial หรือ RenderAction
ฉันใช้วิธีนี้เพื่อแสดงข้อมูลของผู้ใช้ที่ล็อกอินเช่นชื่อรูปโปรไฟล์และอื่น ๆ
คำถามเก่า แต่พูดถึงวิธีแก้ปัญหาสำหรับนักพัฒนา MVC5 คุณสามารถใช้Modelคุณสมบัติเดียวกับในมุมมอง
Modelคุณสมบัติทั้งในมุมมองและรูปแบบเป็น assosiated ด้วยเหมือนกันViewDataDictionaryวัตถุดังนั้นคุณจึงไม่ต้องทำงานพิเศษใด ๆ ที่จะผ่านรูปแบบของคุณไปยังหน้ารูปแบบและคุณไม่ได้มีการประกาศ@model MyModelNameในรูปแบบ
แต่แจ้งให้ทราบว่าเมื่อคุณใช้@Model.XXXในรูปแบบเมนูบริบท IntelliSense จะไม่ปรากฏเพราะที่นี่เป็นวัตถุแบบไดนามิกเช่นเดียวกับModelViewBag
บางทีมันอาจจะไม่ใช่วิธีที่เหมาะสมในการจัดการ แต่วิธีแก้ปัญหาที่ง่ายและสมเหตุสมผลที่สุดสำหรับฉันคือแค่สร้างคลาสและสร้างอินสแตนซ์ในเค้าโครง เป็นข้อยกเว้นเพียงครั้งเดียวสำหรับวิธีการทำอย่างอื่นที่ถูกต้อง หากทำได้มากกว่าในเค้าโครงคุณต้องคิดใหม่อย่างจริงจังว่ากำลังทำอะไรอยู่และอาจอ่านบทแนะนำเพิ่มเติมก่อนที่จะดำเนินการต่อในโครงการของคุณ
public class MyLayoutModel {
    public User CurrentUser {
        get {
            .. get the current user ..
        }
    }
}
จากนั้นในมุมมอง
@{
    // Or get if from your DI container
    var myLayoutModel = new MyLayoutModel();
}
ใน. net core คุณสามารถข้ามสิ่งนั้นและใช้การฉีดพึ่งพาได้
@inject My.Namespace.IMyLayoutModel myLayoutModel
เป็นหนึ่งในพื้นที่ที่มีความร่มรื่น แต่ด้วยทางเลือกที่ซับซ้อนมาก ๆ ที่ฉันเห็นที่นี่ฉันคิดว่ามันเป็นมากกว่าข้อยกเว้นที่โอเคที่จะทำในนามของการปฏิบัติจริง โดยเฉพาะอย่างยิ่งถ้าคุณทำให้มันง่ายและตรวจสอบให้แน่ใจว่าตรรกะหนัก ๆ (ฉันขอยืนยันว่าไม่ควรมีจริง ๆ แต่ข้อกำหนดต่างกัน) อยู่ในคลาส / เลเยอร์อื่นที่เป็นของมัน ย่อมดีกว่าการสร้างมลพิษให้กับคอนโทรลเลอร์หรือรุ่นทั้งหมดของคุณเพื่อประโยชน์ในการมองเห็นเพียงด้านเดียว ..
มีวิธีอื่นในการเก็บถาวร
เพียงแค่ใช้ระดับ BaseController สำหรับตัวควบคุมทั้งหมด
ในBaseControllerคลาสสร้างเมธอดที่ส่งคืนคลาส Model เช่นอินสแตนซ์
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 ที่มีนิยามคลาสสำหรับออบเจ็กต์ของคุณ ตัวอย่างเช่น:
@ ใช้ YourApplication.YourClasses;
3) เมื่อคุณอ้างอิง yourObject ใน _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ใหม่