Những gì tôi thấy là một thuộc tính Bố cục chuỗi. Nhưng làm cách nào để chuyển một mô hình sang bố cục một cách rõ ràng?
Model
có sẵn trong _Layout
. Tôi đang sử dụng MVC5.
Những gì tôi thấy là một thuộc tính Bố cục chuỗi. Nhưng làm cách nào để chuyển một mô hình sang bố cục một cách rõ ràng?
Model
có sẵn trong _Layout
. Tôi đang sử dụng MVC5.
Câu trả lời:
Có vẻ như bạn đã lập mô hình các mô hình xem của mình hơi sai nếu bạn gặp sự cố này.
Cá nhân tôi sẽ không bao giờ gõ một trang bố cục. Nhưng nếu bạn muốn làm điều đó, bạn nên có một mô hình xem cơ sở mà các mô hình xem khác của bạn kế thừa và nhập bố cục của bạn vào mô hình xem cơ sở và bạn chuyển các trang cụ thể một lần.
Ví dụ: Bộ điều khiển:
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;
}
}
Ví dụ trên cùng của Trang bố cục
@{
var viewModel = (MainLayoutViewModel)ViewBag.MainLayoutViewModel;
}
Bây giờ bạn có thể tham chiếu đến biến 'viewModel' trong trang bố cục của mình với toàn quyền truy cập vào đối tượng đã nhập.
Tôi thích cách tiếp cận này vì nó là bộ điều khiển kiểm soát bố cục, trong khi các mô hình xem trang riêng lẻ vẫn là bố cục bất khả tri.
Ghi chú cho MVC Core
IActionFilter
và thực hiện cùng một công việc trong OnActionExecuting
. Mặc MyActionFilter
vào của bạn 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;
}
}
}
đây là công cụ khá cơ bản, tất cả những gì bạn cần làm là tạo mô hình chế độ xem cơ sở và đảm bảo TẤT CẢ! và ý tôi là TẤT CẢ! trong số các chế độ xem của bạn sẽ sử dụng bố cục đó sẽ nhận được các chế độ xem sử dụng mô hình cơ sở đó!
public class SomeViewModel : ViewModelBase
{
public bool ImNotEmpty = true;
}
public class EmptyViewModel : ViewModelBase
{
}
public abstract class ViewModelBase
{
}
trong _Layout.cshtml:
@model Models.ViewModelBase
<!DOCTYPE html>
<html>
and so on...
trong phương thức Chỉ mục (ví dụ) trong bộ điều khiển gia đình:
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">
tôi không đồng ý rằng việc chuyển một mô hình tới _layout là một lỗi, một số thông tin người dùng có thể được chuyển và dữ liệu có thể được đưa vào chuỗi kế thừa bộ điều khiển, vì vậy chỉ cần một lần triển khai.
rõ ràng cho mục đích nâng cao hơn, bạn nên xem xét việc tạo văn bản tĩnh tùy chỉnh bằng cách sử dụng tiêm và bao gồm không gian tên mô hình đó trong _Layout.cshtml.
nhưng đối với người dùng cơ bản, điều này sẽ thực hiện thủ thuật
Một giải pháp phổ biến là tạo mô hình dạng xem cơ sở chứa các thuộc tính được sử dụng trong tệp bố cục và sau đó kế thừa từ mô hình cơ sở sang các mô hình được sử dụng trên các trang tương ứng.
Vấn đề với cách tiếp cận này là bây giờ bạn đã tự nhốt mình vào vấn đề một mô hình chỉ có thể kế thừa từ một lớp khác, và có thể giải pháp của bạn là bạn không thể sử dụng kế thừa trên mô hình mà bạn dự định.
Giải pháp của tôi cũng bắt đầu với mô hình chế độ xem cơ sở:
public class LayoutModel
{
public LayoutModel(string title)
{
Title = title;
}
public string Title { get;}
}
Những gì tôi sử dụng sau đó là phiên bản chung của LayoutModel kế thừa từ LayoutModel, như sau:
public class LayoutModel<T> : LayoutModel
{
public LayoutModel(T pageModel, string title) : base(title)
{
PageModel = pageModel;
}
public T PageModel { get; }
}
Với giải pháp này, tôi đã ngắt kết nối nhu cầu thừa kế giữa mô hình bố trí và mô hình.
Vì vậy, bây giờ tôi có thể tiếp tục và sử dụng LayoutModel trong Layout.cshtml như sau:
@model LayoutModel
<!doctype html>
<html>
<head>
<title>@Model.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>
Và trên một trang, bạn có thể sử dụng LayoutModel chung như thế này:
@model LayoutModel<Customer>
@{
var customer = Model.PageModel;
}
<p>Customer name: @customer.Name</p>
Từ bộ điều khiển của bạn, bạn chỉ cần trả về một mô hình kiểu LayoutModel:
public ActionResult Page()
{
return View(new LayoutModel<Customer>(new Customer() { Name = "Test" }, "Title");
}
Tại sao bạn không thêm Chế độ xem từng phần mới với bộ điều khiển cụ thể của riêng tôi chuyển mô hình được yêu cầu sang chế độ xem từng phần và cuối cùng Hiển thị chế độ xem từng phần được đề cập trên Layout.cshtml của bạn bằng cách sử dụng RenderPartial hoặc RenderAction?
Tôi sử dụng phương pháp này để hiển thị thông tin của người dùng đã đăng nhập như tên, ảnh hồ sơ, v.v.
câu hỏi cũ nhưng chỉ đề cập đến giải pháp cho các nhà phát triển MVC5, bạn có thể sử dụng thuộc Model
tính giống như trong chế độ xem.
Các Model
bất động sản trong cả hai quan điểm và bố trí được assosiated với cùng ViewDataDictionary
đối tượng, vì vậy bạn không cần phải làm bất cứ việc làm thêm để vượt qua mô hình của bạn để trang bố trí, và bạn không phải khai báo @model MyModelName
trong cách bố trí.
Nhưng lưu ý rằng khi bạn sử dụng @Model.XXX
trong layout, menu ngữ cảnh intelliSense sẽ không xuất hiện vì Model
ở đây là một đối tượng động giống như ViewBag
.
Có thể về mặt kỹ thuật không phải là cách thích hợp để xử lý nó, nhưng giải pháp đơn giản và hợp lý nhất đối với tôi là chỉ tạo một lớp và tạo nó trong bố cục. Nó là một ngoại lệ một lần đối với cách làm đúng khác. Nếu điều này được thực hiện nhiều hơn so với bố cục thì bạn cần phải nghiêm túc suy nghĩ lại những gì bạn đang làm và có thể đọc thêm một vài hướng dẫn trước khi tiếp tục thực hiện dự án của mình.
public class MyLayoutModel {
public User CurrentUser {
get {
.. get the current user ..
}
}
}
sau đó trong quan điểm
@{
// Or get if from your DI container
var myLayoutModel = new MyLayoutModel();
}
trong lõi .net, bạn thậm chí có thể bỏ qua điều đó và sử dụng tính năng tiêm phụ thuộc.
@inject My.Namespace.IMyLayoutModel myLayoutModel
Đó là một trong những khu vực khá mờ ám. Nhưng với những lựa chọn thay thế cực kỳ phức tạp mà tôi đang thấy ở đây, tôi nghĩ rằng nó không phải là một ngoại lệ phù hợp để thực hiện nhân danh tính thực tế. Đặc biệt nếu bạn đảm bảo giữ cho nó đơn giản và đảm bảo rằng mọi logic nặng nề (tôi sẽ tranh luận rằng thực sự không nên có bất kỳ điều gì, nhưng các yêu cầu khác nhau) nằm trong một lớp / lớp khác nơi nó thuộc về. Nó chắc chắn tốt hơn là làm ô nhiễm TẤT CẢ các bộ điều khiển hoặc mô hình của bạn vì lợi ích về cơ bản chỉ là một chế độ xem ..
Có một cách khác để lưu trữ nó.
Chỉ cần triển khai lớp BaseController cho tất cả các bộ điều khiển .
Trong BaseController
lớp, hãy tạo một phương thức trả về một lớp Model chẳng hạn.
public MenuPageModel GetTopMenu() { var m = new MenuPageModel(); // populate your model here return m; }
Layout
trang, bạn có thể gọi phương thức đó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>
Giả sử mô hình của bạn là một tập hợp các đối tượng (hoặc có thể là một đối tượng duy nhất). Đối với mỗi đối tượng trong mô hình, hãy làm như sau.
1) Đặt đối tượng bạn muốn hiển thị trong ViewBag. Ví dụ:
ViewBag.YourObject = yourObject;
2) Thêm câu lệnh using ở đầu _Layout.cshtml chứa định nghĩa lớp cho các đối tượng của bạn. Ví dụ:
@ sử dụng YourApplication.YourClasses;
3) Khi bạn tham chiếu yourObject trong _Layout truyền nó. Bạn có thể áp dụng diễn viên vì những gì bạn đã làm trong (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; }
}
Sử dụng IContainsMyModel trong bố cục của bạn.
Đã giải quyết. Quy tắc giao diện.
Ví dụ
@model IList<Model.User>
@{
Layout="~/Views/Shared/SiteLayout.cshtml";
}
Đọc thêm về chỉ thị @model mới