我看到的是一个字符串Layout属性。但是如何将模型明确传递给布局?
Model
在中可用_Layout
。我正在使用MVC5。
我看到的是一个字符串Layout属性。但是如何将模型明确传递给布局?
Model
在中可用_Layout
。我正在使用MVC5。
Answers:
如果您遇到此问题,似乎您对视图模型进行了建模有点错误。
就我个人而言,我永远不会键入布局页面。但是,如果要执行此操作,则应该有一个继承其他视图模型的基础视图模型,然后将布局键入基础视图模型,然后将页面分页到特定视图。
示例:控制器:
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
。穿上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...
在家庭控制器的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是错误的,可以传递一些用户信息,并且可以在控制器继承链中填充数据,因此仅需要一个实现。
显然,出于更高级的目的,您应该考虑使用注入创建自定义静态contaxt,并将该模型名称空间包含在_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; }
}
通过此解决方案,我不再需要在布局模型和模型之间继承。
现在,我可以像这样在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>
从您的控制器中,您只需返回LayoutModel类型的模型:
public ActionResult Page()
{
return View(new LayoutModel<Customer>(new Customer() { Name = "Test" }, "Title");
}
为什么不使用我自己的特定控制器添加新的Partial View,将所需的模型传递给Partial View,最后使用RenderPartial或RenderAction在Layout.cshtml上渲染提及的Partial View?
我使用这种方法来显示已登录用户的信息,例如姓名,个人资料图片等。
也许从技术上讲,这不是正确的处理方法,但是对我来说,最简单,最合理的解决方案是只创建一个类并在布局中实例化它。这是一次性的例外方式,否则它是正确的方式。如果这样做比在布局中做得更多,那么您需要认真地重新考虑您的工作,并可能在继续进行项目之前阅读更多的教程。
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
类中,创建一个返回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>
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。
解决了。接口规则。